Merge branch 'master' into grpc-rs

This commit is contained in:
Paul Hauner
2019-01-22 12:58:17 +11:00
21 changed files with 1005 additions and 471 deletions

View File

@@ -1,43 +1,32 @@
use bls::{Signature, BLS_AGG_SIG_BYTE_SIZE};
use spec::ChainSpec;
use ssz::{encode::encode_length, Decodable, LENGTH_BYTES};
use types::{BeaconBlock, BeaconBlockBody, Hash256};
/// Generate a genesis BeaconBlock.
pub fn genesis_beacon_block(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock {
BeaconBlock {
slot: spec.initial_slot_number,
slot: spec.genesis_slot_number,
parent_root: spec.zero_hash,
state_root,
randao_reveal: spec.zero_hash,
candidate_pow_receipt_root: spec.zero_hash,
signature: genesis_signature(),
signature: spec.empty_signature.clone(),
body: BeaconBlockBody {
proposer_slashings: vec![],
casper_slashings: vec![],
attestations: vec![],
custody_reseeds: vec![],
custody_challenges: vec![],
custody_responses: vec![],
deposits: vec![],
exits: vec![],
},
}
}
fn genesis_signature() -> Signature {
let mut bytes = encode_length(BLS_AGG_SIG_BYTE_SIZE, LENGTH_BYTES);
bytes.append(&mut vec![0; BLS_AGG_SIG_BYTE_SIZE]);
let (signature, _) = match Signature::ssz_decode(&bytes, 0) {
Ok(sig) => sig,
Err(_) => unreachable!(),
};
signature
}
#[cfg(test)]
mod tests {
use super::*;
// TODO: enhance these tests.
// https://github.com/sigp/lighthouse/issues/117
use bls::Signature;
#[test]
fn test_genesis() {
@@ -47,4 +36,54 @@ mod tests {
// This only checks that the function runs without panic.
genesis_beacon_block(state_root, &spec);
}
#[test]
fn test_zero_items() {
let spec = ChainSpec::foundation();
let state_root = Hash256::zero();
let genesis_block = genesis_beacon_block(state_root, &spec);
assert!(genesis_block.slot == 0);
assert!(genesis_block.parent_root.is_zero());
assert!(genesis_block.randao_reveal.is_zero());
assert!(genesis_block.candidate_pow_receipt_root.is_zero()); // aka deposit_root
}
#[test]
fn test_beacon_body() {
let spec = ChainSpec::foundation();
let state_root = Hash256::zero();
let genesis_block = genesis_beacon_block(state_root, &spec);
// Custody items are not being implemented until phase 1 so tests to be added later
assert!(genesis_block.body.proposer_slashings.is_empty());
assert!(genesis_block.body.casper_slashings.is_empty());
assert!(genesis_block.body.attestations.is_empty());
assert!(genesis_block.body.deposits.is_empty());
assert!(genesis_block.body.exits.is_empty());
}
#[test]
fn test_signature() {
let spec = ChainSpec::foundation();
let state_root = Hash256::zero();
let genesis_block = genesis_beacon_block(state_root, &spec);
// Signature should consist of [bytes48(0), bytes48(0)]
// Note this is implemented using Apache Milagro BLS which requires one extra byte -> 97bytes
let raw_sig = genesis_block.signature.as_raw();
let raw_sig_bytes = raw_sig.as_bytes();
for item in raw_sig_bytes.iter() {
assert!(*item == 0);
}
assert_eq!(genesis_block.signature, Signature::empty_signature());
}
}

View File

@@ -21,7 +21,7 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result<BeaconState, Error> {
};
let initial_crosslink = CrosslinkRecord {
slot: spec.initial_slot_number,
slot: spec.genesis_slot_number,
shard_block_root: spec.zero_hash,
};
@@ -29,43 +29,54 @@ pub fn genesis_beacon_state(spec: &ChainSpec) -> Result<BeaconState, Error> {
/*
* Misc
*/
slot: spec.initial_slot_number,
slot: spec.genesis_slot_number,
genesis_time: spec.genesis_time,
fork_data: ForkData {
pre_fork_version: spec.initial_fork_version,
post_fork_version: spec.initial_fork_version,
fork_slot: spec.initial_slot_number,
pre_fork_version: spec.genesis_fork_version,
post_fork_version: spec.genesis_fork_version,
fork_slot: spec.genesis_slot_number,
},
/*
* Validator registry
*/
validator_registry: spec.initial_validators.clone(),
validator_balances: spec.initial_balances.clone(),
validator_registry_latest_change_slot: spec.initial_slot_number,
validator_registry_latest_change_slot: spec.genesis_slot_number,
validator_registry_exit_count: 0,
validator_registry_delta_chain_tip: spec.zero_hash,
/*
* Randomness and committees
*/
randao_mix: spec.zero_hash,
next_seed: spec.zero_hash,
shard_committees_at_slots: vec![],
persistent_committees: vec![],
persistent_committee_reassignments: vec![],
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize],
latest_vdf_outputs: vec![
spec.zero_hash;
(spec.latest_randao_mixes_length / spec.epoch_length) as usize
],
previous_epoch_start_shard: spec.genesis_start_shard,
current_epoch_start_shard: spec.genesis_start_shard,
previous_epoch_calculation_slot: spec.genesis_slot_number,
current_epoch_calculation_slot: spec.genesis_slot_number,
previous_epoch_randao_mix: spec.zero_hash,
current_epoch_randao_mix: spec.zero_hash,
/*
* Custody challenges
*/
custody_challenges: vec![],
/*
* Finality
*/
previous_justified_slot: spec.initial_slot_number,
justified_slot: spec.initial_slot_number,
previous_justified_slot: spec.genesis_slot_number,
justified_slot: spec.genesis_slot_number,
justification_bitfield: 0,
finalized_slot: spec.initial_slot_number,
finalized_slot: spec.genesis_slot_number,
/*
* Recent state
*/
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize],
latest_block_roots: vec![spec.zero_hash; spec.epoch_length as usize],
latest_penalized_exit_balances: vec![],
latest_block_roots: vec![spec.zero_hash; spec.latest_block_roots_length as usize],
latest_penalized_exit_balances: vec![0; spec.latest_penalized_exit_length as usize],
latest_attestations: vec![],
batched_block_roots: vec![],
/*
* PoW receipt root
*/
@@ -82,16 +93,11 @@ impl From<ValidatorAssignmentError> for Error {
#[cfg(test)]
mod tests {
extern crate bls;
extern crate validator_induction;
use super::*;
// TODO: enhance these tests.
// https://github.com/sigp/lighthouse/issues/117
use types::Hash256;
#[test]
fn test_genesis() {
fn test_genesis_state() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
@@ -101,4 +107,116 @@ mod tests {
spec.initial_validators.len()
);
}
#[test]
fn test_genesis_state_misc() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
assert_eq!(state.slot, 0);
assert_eq!(state.genesis_time, spec.genesis_time);
assert_eq!(state.fork_data.pre_fork_version, 0);
assert_eq!(state.fork_data.post_fork_version, 0);
assert_eq!(state.fork_data.fork_slot, 0);
}
#[test]
fn test_genesis_state_validators() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
assert_eq!(state.validator_registry, spec.initial_validators);
assert_eq!(state.validator_balances, spec.initial_balances);
assert!(state.validator_registry_latest_change_slot == 0);
assert!(state.validator_registry_exit_count == 0);
assert_eq!(state.validator_registry_delta_chain_tip, Hash256::zero());
}
#[test]
fn test_genesis_state_randomness_committees() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
// Array of size 8,192 each being zero_hash
assert_eq!(state.latest_randao_mixes.len(), 8_192);
for item in state.latest_randao_mixes.iter() {
assert_eq!(*item, Hash256::zero());
}
// Array of size 8,192 each being a zero hash
assert_eq!(state.latest_vdf_outputs.len(), (8_192 / 64));
for item in state.latest_vdf_outputs.iter() {
assert_eq!(*item, Hash256::zero());
}
// TODO: Check shard and committee shuffling requires solving issue:
// https://github.com/sigp/lighthouse/issues/151
// initial_shuffling = get_shuffling(Hash256::zero(), &state.validator_registry, 0, 0)
// initial_shuffling = initial_shuffling.append(initial_shuffling.clone());
}
// Custody not implemented until Phase 1
#[test]
fn test_genesis_state_custody() {}
#[test]
fn test_genesis_state_finanilty() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
assert_eq!(state.previous_justified_slot, 0);
assert_eq!(state.justified_slot, 0);
assert_eq!(state.justification_bitfield, 0);
assert_eq!(state.finalized_slot, 0);
}
#[test]
fn test_genesis_state_recent_state() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
// Test latest_crosslinks
assert_eq!(state.latest_crosslinks.len(), 1_024);
for link in state.latest_crosslinks.iter() {
assert_eq!(link.slot, 0);
assert_eq!(link.shard_block_root, Hash256::zero());
}
// Test latest_block_roots
assert_eq!(state.latest_block_roots.len(), 8_192);
for block in state.latest_block_roots.iter() {
assert_eq!(*block, Hash256::zero());
}
// Test latest_penalized_exit_balances
assert_eq!(state.latest_penalized_exit_balances.len(), 8_192);
for item in state.latest_penalized_exit_balances.iter() {
assert!(*item == 0);
}
// Test latest_attestations
assert!(state.latest_attestations.is_empty());
// batched_block_roots
assert!(state.batched_block_roots.is_empty());
}
#[test]
fn test_genesis_state_deposit_root() {
let spec = ChainSpec::foundation();
let state = genesis_beacon_state(&spec).unwrap();
assert_eq!(
state.processed_pow_receipt_root,
spec.processed_pow_receipt_root
);
assert!(state.candidate_pow_receipt_roots.is_empty());
}
}

View File

@@ -1,5 +1,5 @@
use super::ChainSpec;
use bls::{Keypair, PublicKey, SecretKey};
use bls::{Keypair, PublicKey, SecretKey, Signature};
use types::{Address, Hash256, ValidatorRecord};
@@ -17,13 +17,16 @@ impl ChainSpec {
* Misc
*/
shard_count: 1_024,
target_committee_size: 256,
target_committee_size: 128,
ejection_balance: 16,
max_balance_churn_quotient: 32,
gwei_per_eth: u64::pow(10, 9),
beacon_chain_shard_number: u64::max_value(),
bls_withdrawal_prefix_byte: 0x00,
max_casper_votes: 1_024,
latest_block_roots_length: 8_192,
latest_randao_mixes_length: 8_192,
latest_penalized_exit_length: 8_192,
max_withdrawals_per_epoch: 4,
/*
* Deposit contract
*/
@@ -34,32 +37,35 @@ impl ChainSpec {
/*
* Initial Values
*/
initial_fork_version: 0,
initial_slot_number: 0,
genesis_fork_version: 0,
genesis_slot_number: 0,
genesis_start_shard: 0,
far_future_slot: u64::max_value(),
zero_hash: Hash256::zero(),
empty_signature: Signature::empty_signature(),
bls_withdrawal_prefix_byte: 0x00,
/*
* Time parameters
*/
slot_duration: 6,
min_attestation_inclusion_delay: 4,
epoch_length: 64,
min_validator_registry_change_interval: 256,
seed_lookahead: 64,
entry_exit_delay: 256,
pow_receipt_root_voting_period: 1_024,
shard_persistent_committee_change_period: u64::pow(2, 17),
collective_penalty_calculation_period: u64::pow(2, 20),
zero_balance_validator_ttl: u64::pow(2, 22),
min_validator_withdrawal_time: u64::pow(2, 14),
/*
* Reward and penalty quotients
*/
base_reward_quotient: 2_048,
base_reward_quotient: 1_024,
whistleblower_reward_quotient: 512,
includer_reward_quotient: 8,
inactivity_penalty_quotient: u64::pow(2, 34),
inactivity_penalty_quotient: u64::pow(2, 24),
/*
* Max operations per block
*/
max_proposer_slashings: 16,
max_casper_slashings: 15,
max_casper_slashings: 16,
max_attestations: 128,
max_deposits: 16,
max_exits: 16,
@@ -103,9 +109,12 @@ fn initial_validators_for_testing() -> Vec<ValidatorRecord> {
withdrawal_credentials: Hash256::zero(),
randao_commitment: Hash256::zero(),
randao_layers: 0,
status: From::from(0),
latest_status_change_slot: 0,
activation_slot: u64::max_value(),
exit_slot: u64::max_value(),
withdrawal_slot: u64::max_value(),
penalized_slot: u64::max_value(),
exit_count: 0,
status_flags: None,
custody_commitment: Hash256::zero(),
latest_custody_reseed_slot: 0,
penultimate_custody_reseed_slot: 0,

View File

@@ -3,6 +3,7 @@ extern crate types;
mod foundation;
use bls::Signature;
use types::{Address, Hash256, ValidatorRecord};
#[derive(PartialEq, Debug)]
@@ -16,8 +17,11 @@ pub struct ChainSpec {
pub max_balance_churn_quotient: u64,
pub gwei_per_eth: u64,
pub beacon_chain_shard_number: u64,
pub bls_withdrawal_prefix_byte: u8,
pub max_casper_votes: u64,
pub latest_block_roots_length: u64,
pub latest_randao_mixes_length: u64,
pub latest_penalized_exit_length: u64,
pub max_withdrawals_per_epoch: u64,
/*
* Deposit contract
*/
@@ -28,20 +32,23 @@ pub struct ChainSpec {
/*
* Initial Values
*/
pub initial_fork_version: u64,
pub initial_slot_number: u64,
pub genesis_fork_version: u64,
pub genesis_slot_number: u64,
pub genesis_start_shard: u64,
pub far_future_slot: u64,
pub zero_hash: Hash256,
pub empty_signature: Signature,
pub bls_withdrawal_prefix_byte: u8,
/*
* Time parameters
*/
pub slot_duration: u64,
pub min_attestation_inclusion_delay: u64,
pub epoch_length: u64,
pub min_validator_registry_change_interval: u64,
pub pow_receipt_root_voting_period: u64,
pub shard_persistent_committee_change_period: u64,
pub collective_penalty_calculation_period: u64,
pub zero_balance_validator_ttl: u64,
pub seed_lookahead: u64,
pub entry_exit_delay: u64,
pub pow_receipt_root_voting_period: u64, // a.k.a. deposit_root_voting_period
pub min_validator_withdrawal_time: u64,
/*
* Reward and penalty quotients
*/

View File

@@ -0,0 +1,60 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use rand::RngCore;
use crate::test_utils::TestRandom;
use super::AttestationData;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct AttestationDataAndCustodyBit {
pub data: AttestationData,
pub custody_bit: bool,
}
impl Encodable for AttestationDataAndCustodyBit {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.data);
s.append(&self.custody_bit);
}
}
impl Decodable for AttestationDataAndCustodyBit {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (data, i) = <_>::ssz_decode(bytes, i)?;
let (custody_bit, i) = <_>::ssz_decode(bytes, i)?;
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
data,
custody_bit,
};
Ok((attestation_data_and_custody_bit, i))
}
}
impl<T: RngCore> TestRandom<T> for AttestationDataAndCustodyBit {
fn random_for_test(rng: &mut T) -> Self {
Self {
data: <_>::random_for_test(rng),
custody_bit: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod test {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use super::*;
use super::super::ssz::ssz_encode;
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = AttestationDataAndCustodyBit::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@@ -3,11 +3,20 @@ use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing};
use crate::test_utils::TestRandom;
use rand::RngCore;
// The following types are just dummy classes as they will not be defined until
// Phase 1 (Sharding phase)
type CustodyReseed = usize;
type CustodyChallenge = usize;
type CustodyResponse = usize;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct BeaconBlockBody {
pub proposer_slashings: Vec<ProposerSlashing>,
pub casper_slashings: Vec<CasperSlashing>,
pub attestations: Vec<Attestation>,
pub custody_reseeds: Vec<CustodyReseed>,
pub custody_challenges: Vec<CustodyChallenge>,
pub custody_responses: Vec<CustodyResponse>,
pub deposits: Vec<Deposit>,
pub exits: Vec<Exit>,
}
@@ -17,6 +26,9 @@ impl Encodable for BeaconBlockBody {
s.append_vec(&self.proposer_slashings);
s.append_vec(&self.casper_slashings);
s.append_vec(&self.attestations);
s.append_vec(&self.custody_reseeds);
s.append_vec(&self.custody_challenges);
s.append_vec(&self.custody_responses);
s.append_vec(&self.deposits);
s.append_vec(&self.exits);
}
@@ -27,6 +39,9 @@ impl Decodable for BeaconBlockBody {
let (proposer_slashings, i) = <_>::ssz_decode(bytes, i)?;
let (casper_slashings, i) = <_>::ssz_decode(bytes, i)?;
let (attestations, i) = <_>::ssz_decode(bytes, i)?;
let (custody_reseeds, i) = <_>::ssz_decode(bytes, i)?;
let (custody_challenges, i) = <_>::ssz_decode(bytes, i)?;
let (custody_responses, i) = <_>::ssz_decode(bytes, i)?;
let (deposits, i) = <_>::ssz_decode(bytes, i)?;
let (exits, i) = <_>::ssz_decode(bytes, i)?;
@@ -35,6 +50,9 @@ impl Decodable for BeaconBlockBody {
proposer_slashings,
casper_slashings,
attestations,
custody_reseeds,
custody_challenges,
custody_responses,
deposits,
exits,
},
@@ -49,6 +67,9 @@ impl<T: RngCore> TestRandom<T> for BeaconBlockBody {
proposer_slashings: <_>::random_for_test(rng),
casper_slashings: <_>::random_for_test(rng),
attestations: <_>::random_for_test(rng),
custody_reseeds: <_>::random_for_test(rng),
custody_challenges: <_>::random_for_test(rng),
custody_responses: <_>::random_for_test(rng),
deposits: <_>::random_for_test(rng),
exits: <_>::random_for_test(rng),
}

View File

@@ -2,8 +2,6 @@ use super::candidate_pow_receipt_root_record::CandidatePoWReceiptRootRecord;
use super::crosslink_record::CrosslinkRecord;
use super::fork_data::ForkData;
use super::pending_attestation_record::PendingAttestationRecord;
use super::shard_committee::ShardCommittee;
use super::shard_reassignment_record::ShardReassignmentRecord;
use super::validator_record::ValidatorRecord;
use super::Hash256;
use crate::test_utils::TestRandom;
@@ -11,6 +9,9 @@ use hashing::canonical_hash;
use rand::RngCore;
use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream};
// Custody will not be added to the specs until Phase 1 (Sharding Phase) so dummy class used.
type CustodyChallenge = usize;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct BeaconState {
// Misc
@@ -26,11 +27,17 @@ pub struct BeaconState {
pub validator_registry_delta_chain_tip: Hash256,
// Randomness and committees
pub randao_mix: Hash256,
pub next_seed: Hash256,
pub shard_committees_at_slots: Vec<Vec<ShardCommittee>>,
pub persistent_committees: Vec<Vec<u32>>,
pub persistent_committee_reassignments: Vec<ShardReassignmentRecord>,
pub latest_randao_mixes: Vec<Hash256>,
pub latest_vdf_outputs: Vec<Hash256>,
pub previous_epoch_start_shard: u64,
pub current_epoch_start_shard: u64,
pub previous_epoch_calculation_slot: u64,
pub current_epoch_calculation_slot: u64,
pub previous_epoch_randao_mix: Hash256,
pub current_epoch_randao_mix: Hash256,
// Custody challenges
pub custody_challenges: Vec<CustodyChallenge>,
// Finality
pub previous_justified_slot: u64,
@@ -43,8 +50,9 @@ pub struct BeaconState {
pub latest_block_roots: Vec<Hash256>,
pub latest_penalized_exit_balances: Vec<u64>,
pub latest_attestations: Vec<PendingAttestationRecord>,
pub batched_block_roots: Vec<Hash256>,
// PoW receipt root
// PoW receipt root (a.k.a. deposit root)
pub processed_pow_receipt_root: Hash256,
pub candidate_pow_receipt_roots: Vec<CandidatePoWReceiptRootRecord>,
}
@@ -67,11 +75,15 @@ impl Encodable for BeaconState {
s.append(&self.validator_registry_latest_change_slot);
s.append(&self.validator_registry_exit_count);
s.append(&self.validator_registry_delta_chain_tip);
s.append(&self.randao_mix);
s.append(&self.next_seed);
s.append(&self.shard_committees_at_slots);
s.append(&self.persistent_committees);
s.append(&self.persistent_committee_reassignments);
s.append(&self.latest_randao_mixes);
s.append(&self.latest_vdf_outputs);
s.append(&self.previous_epoch_start_shard);
s.append(&self.current_epoch_start_shard);
s.append(&self.previous_epoch_calculation_slot);
s.append(&self.current_epoch_calculation_slot);
s.append(&self.previous_epoch_randao_mix);
s.append(&self.current_epoch_randao_mix);
s.append(&self.custody_challenges);
s.append(&self.previous_justified_slot);
s.append(&self.justified_slot);
s.append(&self.justification_bitfield);
@@ -80,6 +92,7 @@ impl Encodable for BeaconState {
s.append(&self.latest_block_roots);
s.append(&self.latest_penalized_exit_balances);
s.append(&self.latest_attestations);
s.append(&self.batched_block_roots);
s.append(&self.processed_pow_receipt_root);
s.append(&self.candidate_pow_receipt_roots);
}
@@ -95,11 +108,15 @@ impl Decodable for BeaconState {
let (validator_registry_latest_change_slot, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_exit_count, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_delta_chain_tip, i) = <_>::ssz_decode(bytes, i)?;
let (randao_mix, i) = <_>::ssz_decode(bytes, i)?;
let (next_seed, i) = <_>::ssz_decode(bytes, i)?;
let (shard_committees_at_slots, i) = <_>::ssz_decode(bytes, i)?;
let (persistent_committees, i) = <_>::ssz_decode(bytes, i)?;
let (persistent_committee_reassignments, i) = <_>::ssz_decode(bytes, i)?;
let (latest_randao_mixes, i) = <_>::ssz_decode(bytes, i)?;
let (latest_vdf_outputs, i) = <_>::ssz_decode(bytes, i)?;
let (previous_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
let (previous_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
let (current_epoch_calculation_slot, i) = <_>::ssz_decode(bytes, i)?;
let (previous_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?;
let (current_epoch_randao_mix, i) = <_>::ssz_decode(bytes, i)?;
let (custody_challenges, i) = <_>::ssz_decode(bytes, i)?;
let (previous_justified_slot, i) = <_>::ssz_decode(bytes, i)?;
let (justified_slot, i) = <_>::ssz_decode(bytes, i)?;
let (justification_bitfield, i) = <_>::ssz_decode(bytes, i)?;
@@ -108,6 +125,7 @@ impl Decodable for BeaconState {
let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?;
let (latest_penalized_exit_balances, i) = <_>::ssz_decode(bytes, i)?;
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
let (batched_block_roots, i) = <_>::ssz_decode(bytes, i)?;
let (processed_pow_receipt_root, i) = <_>::ssz_decode(bytes, i)?;
let (candidate_pow_receipt_roots, i) = <_>::ssz_decode(bytes, i)?;
@@ -121,11 +139,15 @@ impl Decodable for BeaconState {
validator_registry_latest_change_slot,
validator_registry_exit_count,
validator_registry_delta_chain_tip,
randao_mix,
next_seed,
shard_committees_at_slots,
persistent_committees,
persistent_committee_reassignments,
latest_randao_mixes,
latest_vdf_outputs,
previous_epoch_start_shard,
current_epoch_start_shard,
previous_epoch_calculation_slot,
current_epoch_calculation_slot,
previous_epoch_randao_mix,
current_epoch_randao_mix,
custody_challenges,
previous_justified_slot,
justified_slot,
justification_bitfield,
@@ -134,6 +156,7 @@ impl Decodable for BeaconState {
latest_block_roots,
latest_penalized_exit_balances,
latest_attestations,
batched_block_roots,
processed_pow_receipt_root,
candidate_pow_receipt_roots,
},
@@ -153,11 +176,15 @@ impl<T: RngCore> TestRandom<T> for BeaconState {
validator_registry_latest_change_slot: <_>::random_for_test(rng),
validator_registry_exit_count: <_>::random_for_test(rng),
validator_registry_delta_chain_tip: <_>::random_for_test(rng),
randao_mix: <_>::random_for_test(rng),
next_seed: <_>::random_for_test(rng),
shard_committees_at_slots: <_>::random_for_test(rng),
persistent_committees: <_>::random_for_test(rng),
persistent_committee_reassignments: <_>::random_for_test(rng),
latest_randao_mixes: <_>::random_for_test(rng),
latest_vdf_outputs: <_>::random_for_test(rng),
previous_epoch_start_shard: <_>::random_for_test(rng),
current_epoch_start_shard: <_>::random_for_test(rng),
previous_epoch_calculation_slot: <_>::random_for_test(rng),
current_epoch_calculation_slot: <_>::random_for_test(rng),
previous_epoch_randao_mix: <_>::random_for_test(rng),
current_epoch_randao_mix: <_>::random_for_test(rng),
custody_challenges: <_>::random_for_test(rng),
previous_justified_slot: <_>::random_for_test(rng),
justified_slot: <_>::random_for_test(rng),
justification_bitfield: <_>::random_for_test(rng),
@@ -166,6 +193,7 @@ impl<T: RngCore> TestRandom<T> for BeaconState {
latest_block_roots: <_>::random_for_test(rng),
latest_penalized_exit_balances: <_>::random_for_test(rng),
latest_attestations: <_>::random_for_test(rng),
batched_block_roots: <_>::random_for_test(rng),
processed_pow_receipt_root: <_>::random_for_test(rng),
candidate_pow_receipt_roots: <_>::random_for_test(rng),
}

View File

@@ -3,6 +3,7 @@ use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
// Note: this is refer to as DepositRootVote in specs
#[derive(Debug, PartialEq, Clone)]
pub struct CandidatePoWReceiptRootRecord {
pub candidate_pow_receipt_root: Hash256,

View File

@@ -26,6 +26,7 @@ pub mod shard_reassignment_record;
pub mod slashable_vote_data;
pub mod special_record;
pub mod validator_record;
pub mod validator_registry;
pub mod readers;
@@ -50,7 +51,7 @@ pub use crate::proposer_slashing::ProposerSlashing;
pub use crate::shard_committee::ShardCommittee;
pub use crate::slashable_vote_data::SlashableVoteData;
pub use crate::special_record::{SpecialRecord, SpecialRecordKind};
pub use crate::validator_record::{ValidatorRecord, ValidatorStatus};
pub use crate::validator_record::{StatusFlags as ValidatorStatusFlags, ValidatorRecord};
pub type Hash256 = H256;
pub type Address = H160;

View File

@@ -3,29 +3,43 @@ use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
use ssz::{Decodable, DecodeError, Encodable, SszStream};
use std::convert;
const STATUS_FLAG_INITIATED_EXIT: u8 = 1;
const STATUS_FLAG_WITHDRAWABLE: u8 = 2;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ValidatorStatus {
PendingActivation,
Active,
PendingExit,
PendingWithdraw,
Withdrawn,
Penalized,
pub enum StatusFlags {
InitiatedExit,
Withdrawable,
}
impl convert::From<u8> for ValidatorStatus {
fn from(status: u8) -> Self {
match status {
0 => ValidatorStatus::PendingActivation,
1 => ValidatorStatus::Active,
2 => ValidatorStatus::PendingExit,
3 => ValidatorStatus::PendingWithdraw,
5 => ValidatorStatus::Withdrawn,
127 => ValidatorStatus::Penalized,
_ => unreachable!(),
struct StatusFlagsDecodeError;
impl From<StatusFlagsDecodeError> for DecodeError {
fn from(_: StatusFlagsDecodeError) -> DecodeError {
DecodeError::Invalid
}
}
/// Handles the serialization logic for the `status_flags` field of the `ValidatorRecord`.
fn status_flag_to_byte(flag: Option<StatusFlags>) -> u8 {
if let Some(flag) = flag {
match flag {
StatusFlags::InitiatedExit => STATUS_FLAG_INITIATED_EXIT,
StatusFlags::Withdrawable => STATUS_FLAG_WITHDRAWABLE,
}
} else {
0
}
}
/// Handles the deserialization logic for the `status_flags` field of the `ValidatorRecord`.
fn status_flag_from_byte(flag: u8) -> Result<Option<StatusFlags>, StatusFlagsDecodeError> {
match flag {
0 => Ok(None),
1 => Ok(Some(StatusFlags::InitiatedExit)),
2 => Ok(Some(StatusFlags::Withdrawable)),
_ => Err(StatusFlagsDecodeError),
}
}
@@ -35,61 +49,49 @@ pub struct ValidatorRecord {
pub withdrawal_credentials: Hash256,
pub randao_commitment: Hash256,
pub randao_layers: u64,
pub status: ValidatorStatus,
pub latest_status_change_slot: u64,
pub activation_slot: u64,
pub exit_slot: u64,
pub withdrawal_slot: u64,
pub penalized_slot: u64,
pub exit_count: u64,
pub status_flags: Option<StatusFlags>,
pub custody_commitment: Hash256,
pub latest_custody_reseed_slot: u64,
pub penultimate_custody_reseed_slot: u64,
}
impl ValidatorRecord {
pub fn status_is(&self, status: ValidatorStatus) -> bool {
self.status == status
/// This predicate indicates if the validator represented by this record is considered "active" at `slot`.
pub fn is_active_at(&self, slot: u64) -> bool {
self.activation_slot <= slot && slot < self.exit_slot
}
}
impl Encodable for ValidatorStatus {
fn ssz_append(&self, s: &mut SszStream) {
let byte: u8 = match self {
ValidatorStatus::PendingActivation => 0,
ValidatorStatus::Active => 1,
ValidatorStatus::PendingExit => 2,
ValidatorStatus::PendingWithdraw => 3,
ValidatorStatus::Withdrawn => 5,
ValidatorStatus::Penalized => 127,
};
s.append(&byte);
impl Default for ValidatorRecord {
/// Yields a "default" `ValidatorRecord`. Primarily used for testing.
fn default() -> Self {
Self {
pubkey: PublicKey::default(),
withdrawal_credentials: Hash256::default(),
randao_commitment: Hash256::default(),
randao_layers: 0,
activation_slot: std::u64::MAX,
exit_slot: std::u64::MAX,
withdrawal_slot: std::u64::MAX,
penalized_slot: std::u64::MAX,
exit_count: 0,
status_flags: None,
custody_commitment: Hash256::default(),
latest_custody_reseed_slot: 0, // NOTE: is `GENESIS_SLOT`
penultimate_custody_reseed_slot: 0, // NOTE: is `GENESIS_SLOT`
}
}
}
impl Decodable for ValidatorStatus {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (byte, i) = u8::ssz_decode(bytes, i)?;
let status = match byte {
0 => ValidatorStatus::PendingActivation,
1 => ValidatorStatus::Active,
2 => ValidatorStatus::PendingExit,
3 => ValidatorStatus::PendingWithdraw,
5 => ValidatorStatus::Withdrawn,
127 => ValidatorStatus::Penalized,
_ => return Err(DecodeError::Invalid),
};
Ok((status, i))
}
}
impl<T: RngCore> TestRandom<T> for ValidatorStatus {
impl<T: RngCore> TestRandom<T> for StatusFlags {
fn random_for_test(rng: &mut T) -> Self {
let options = vec![
ValidatorStatus::PendingActivation,
ValidatorStatus::Active,
ValidatorStatus::PendingExit,
ValidatorStatus::PendingWithdraw,
ValidatorStatus::Withdrawn,
ValidatorStatus::Penalized,
];
options[(rng.next_u32() as usize) % options.len()]
let options = vec![StatusFlags::InitiatedExit, StatusFlags::Withdrawable];
options[(rng.next_u32() as usize) % options.len()].clone()
}
}
@@ -99,9 +101,12 @@ impl Encodable for ValidatorRecord {
s.append(&self.withdrawal_credentials);
s.append(&self.randao_commitment);
s.append(&self.randao_layers);
s.append(&self.status);
s.append(&self.latest_status_change_slot);
s.append(&self.activation_slot);
s.append(&self.exit_slot);
s.append(&self.withdrawal_slot);
s.append(&self.penalized_slot);
s.append(&self.exit_count);
s.append(&status_flag_to_byte(self.status_flags));
s.append(&self.custody_commitment);
s.append(&self.latest_custody_reseed_slot);
s.append(&self.penultimate_custody_reseed_slot);
@@ -114,22 +119,30 @@ impl Decodable for ValidatorRecord {
let (withdrawal_credentials, i) = <_>::ssz_decode(bytes, i)?;
let (randao_commitment, i) = <_>::ssz_decode(bytes, i)?;
let (randao_layers, i) = <_>::ssz_decode(bytes, i)?;
let (status, i) = <_>::ssz_decode(bytes, i)?;
let (latest_status_change_slot, i) = <_>::ssz_decode(bytes, i)?;
let (activation_slot, i) = <_>::ssz_decode(bytes, i)?;
let (exit_slot, i) = <_>::ssz_decode(bytes, i)?;
let (withdrawal_slot, i) = <_>::ssz_decode(bytes, i)?;
let (penalized_slot, i) = <_>::ssz_decode(bytes, i)?;
let (exit_count, i) = <_>::ssz_decode(bytes, i)?;
let (status_flags_byte, i): (u8, usize) = <_>::ssz_decode(bytes, i)?;
let (custody_commitment, i) = <_>::ssz_decode(bytes, i)?;
let (latest_custody_reseed_slot, i) = <_>::ssz_decode(bytes, i)?;
let (penultimate_custody_reseed_slot, i) = <_>::ssz_decode(bytes, i)?;
let status_flags = status_flag_from_byte(status_flags_byte)?;
Ok((
Self {
pubkey,
withdrawal_credentials,
randao_commitment,
randao_layers,
status,
latest_status_change_slot,
activation_slot,
exit_slot,
withdrawal_slot,
penalized_slot,
exit_count,
status_flags,
custody_commitment,
latest_custody_reseed_slot,
penultimate_custody_reseed_slot,
@@ -146,9 +159,12 @@ impl<T: RngCore> TestRandom<T> for ValidatorRecord {
withdrawal_credentials: <_>::random_for_test(rng),
randao_commitment: <_>::random_for_test(rng),
randao_layers: <_>::random_for_test(rng),
status: <_>::random_for_test(rng),
latest_status_change_slot: <_>::random_for_test(rng),
activation_slot: <_>::random_for_test(rng),
exit_slot: <_>::random_for_test(rng),
withdrawal_slot: <_>::random_for_test(rng),
penalized_slot: <_>::random_for_test(rng),
exit_count: <_>::random_for_test(rng),
status_flags: Some(<_>::random_for_test(rng)),
custody_commitment: <_>::random_for_test(rng),
latest_custody_reseed_slot: <_>::random_for_test(rng),
penultimate_custody_reseed_slot: <_>::random_for_test(rng),
@@ -174,13 +190,24 @@ mod tests {
}
#[test]
pub fn test_validator_status_ssz_round_trip() {
fn test_validator_can_be_active() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = ValidatorStatus::random_for_test(&mut rng);
let mut validator = ValidatorRecord::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
let activation_slot = u64::random_for_test(&mut rng);
let exit_slot = activation_slot + 234;
assert_eq!(original, decoded);
validator.activation_slot = activation_slot;
validator.exit_slot = exit_slot;
for slot in (activation_slot - 100)..(exit_slot + 100) {
if slot < activation_slot {
assert!(!validator.is_active_at(slot));
} else if slot >= exit_slot {
assert!(!validator.is_active_at(slot));
} else {
assert!(validator.is_active_at(slot));
}
}
}
}

View File

@@ -0,0 +1,171 @@
/// Contains logic to manipulate a `&[ValidatorRecord]`.
/// For now, we avoid defining a newtype and just have flat functions here.
use super::validator_record::*;
/// Given an indexed sequence of `validators`, return the indices corresponding to validators that are active at `slot`.
pub fn get_active_validator_indices(validators: &[ValidatorRecord], slot: u64) -> Vec<usize> {
validators
.iter()
.enumerate()
.filter_map(|(index, validator)| {
if validator.is_active_at(slot) {
Some(index)
} else {
None
}
})
.collect::<Vec<_>>()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
#[test]
fn can_get_empty_active_validator_indices() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let validators = vec![];
let some_slot = u64::random_for_test(&mut rng);
let indices = get_active_validator_indices(&validators, some_slot);
assert_eq!(indices, vec![]);
}
#[test]
fn can_get_no_active_validator_indices() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let mut validators = vec![];
let count_validators = 10;
for _ in 0..count_validators {
validators.push(ValidatorRecord::default())
}
let some_slot = u64::random_for_test(&mut rng);
let indices = get_active_validator_indices(&validators, some_slot);
assert_eq!(indices, vec![]);
}
#[test]
fn can_get_all_active_validator_indices() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let count_validators = 10;
let some_slot = u64::random_for_test(&mut rng);
let mut validators = (0..count_validators)
.into_iter()
.map(|_| {
let mut validator = ValidatorRecord::default();
let activation_offset = u64::random_for_test(&mut rng);
let exit_offset = u64::random_for_test(&mut rng);
validator.activation_slot = some_slot.checked_sub(activation_offset).unwrap_or(0);
validator.exit_slot = some_slot.checked_add(exit_offset).unwrap_or(std::u64::MAX);
validator
})
.collect::<Vec<_>>();
// test boundary condition by ensuring that at least one validator in the list just activated
if let Some(validator) = validators.get_mut(0) {
validator.activation_slot = some_slot;
}
let indices = get_active_validator_indices(&validators, some_slot);
assert_eq!(
indices,
(0..count_validators).into_iter().collect::<Vec<_>>()
);
}
fn set_validators_to_default_entry_exit(validators: &mut [ValidatorRecord]) {
for validator in validators.iter_mut() {
validator.activation_slot = std::u64::MAX;
validator.exit_slot = std::u64::MAX;
}
}
// sets all `validators` to be active as of some slot prior to `slot`. returns the activation slot.
fn set_validators_to_activated(validators: &mut [ValidatorRecord], slot: u64) -> u64 {
let activation_slot = slot - 10;
for validator in validators.iter_mut() {
validator.activation_slot = activation_slot;
}
activation_slot
}
// sets all `validators` to be exited as of some slot before `slot`.
fn set_validators_to_exited(
validators: &mut [ValidatorRecord],
slot: u64,
activation_slot: u64,
) {
assert!(activation_slot < slot);
let mut exit_slot = activation_slot + 10;
while exit_slot >= slot {
exit_slot -= 1;
}
assert!(activation_slot < exit_slot && exit_slot < slot);
for validator in validators.iter_mut() {
validator.exit_slot = exit_slot;
}
}
#[test]
fn can_get_some_active_validator_indices() {
let mut rng = XorShiftRng::from_seed([42; 16]);
const COUNT_PARTITIONS: usize = 3;
const COUNT_VALIDATORS: usize = 3 * COUNT_PARTITIONS;
let some_slot: u64 = u64::random_for_test(&mut rng);
let mut validators = (0..COUNT_VALIDATORS)
.into_iter()
.map(|_| {
let mut validator = ValidatorRecord::default();
let activation_offset = u64::random_for_test(&mut rng);
let exit_offset = u64::random_for_test(&mut rng);
validator.activation_slot = some_slot.checked_sub(activation_offset).unwrap_or(0);
validator.exit_slot = some_slot.checked_add(exit_offset).unwrap_or(std::u64::MAX);
validator
})
.collect::<Vec<_>>();
// we partition the set into partitions based on lifecycle:
for (i, chunk) in validators.chunks_exact_mut(COUNT_PARTITIONS).enumerate() {
match i {
0 => {
// 1. not activated (Default::default())
set_validators_to_default_entry_exit(chunk);
}
1 => {
// 2. activated, but not exited
set_validators_to_activated(chunk, some_slot);
// test boundary condition by ensuring that at least one validator in the list just activated
if let Some(validator) = chunk.get_mut(0) {
validator.activation_slot = some_slot;
}
}
2 => {
// 3. exited
let activation_slot = set_validators_to_activated(chunk, some_slot);
set_validators_to_exited(chunk, some_slot, activation_slot);
// test boundary condition by ensuring that at least one validator in the list just exited
if let Some(validator) = chunk.get_mut(0) {
validator.exit_slot = some_slot;
}
}
_ => unreachable!(
"constants local to this test not in sync with generation of test case"
),
}
}
let indices = get_active_validator_indices(&validators, some_slot);
assert_eq!(indices, vec![3, 4, 5]);
}
}

View File

@@ -2,6 +2,7 @@ use super::SecretKey;
use bls_aggregates::PublicKey as RawPublicKey;
use hex::encode as hex_encode;
use ssz::{decode_ssz_list, ssz_encode, Decodable, DecodeError, Encodable, SszStream};
use std::default;
use std::hash::{Hash, Hasher};
/// A single BLS signature.
@@ -31,6 +32,13 @@ impl PublicKey {
}
}
impl default::Default for PublicKey {
fn default() -> Self {
let secret_key = SecretKey::random();
PublicKey::from_secret_key(&secret_key)
}
}
impl Encodable for PublicKey {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.0.as_bytes());

View File

@@ -35,6 +35,12 @@ impl Signature {
pub fn as_raw(&self) -> &RawSignature {
&self.0
}
/// Returns a new empty signature.
pub fn empty_signature() -> Self {
let empty: Vec<u8> = vec![0; 97];
Signature(RawSignature::from_bytes(&empty).unwrap())
}
}
impl Encodable for Signature {
@@ -68,4 +74,16 @@ mod tests {
assert_eq!(original, decoded);
}
#[test]
pub fn test_empty_signature() {
let sig = Signature::empty_signature();
let sig_as_bytes: Vec<u8> = sig.as_raw().as_bytes();
assert_eq!(sig_as_bytes.len(), 97);
for one_byte in sig_as_bytes.iter() {
assert_eq!(*one_byte, 0);
}
}
}

View File

@@ -1,6 +1,6 @@
use bls::verify_proof_of_possession;
use spec::ChainSpec;
use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus};
use types::{BeaconState, Deposit, ValidatorRecord};
#[derive(Debug, PartialEq, Clone)]
pub enum ValidatorInductionError {
@@ -13,7 +13,7 @@ pub fn process_deposit(
state: &mut BeaconState,
deposit: &Deposit,
spec: &ChainSpec,
) -> Result<usize, ValidatorInductionError> {
) -> Result<(), ValidatorInductionError> {
let deposit_input = &deposit.deposit_data.deposit_input;
let deposit_data = &deposit.deposit_data;
@@ -33,7 +33,7 @@ pub fn process_deposit(
== deposit_input.withdrawal_credentials
{
state.validator_balances[i] += deposit_data.value;
return Ok(i);
return Ok(());
}
Err(ValidatorInductionError::InvalidWithdrawalCredentials)
@@ -44,43 +44,25 @@ pub fn process_deposit(
withdrawal_credentials: deposit_input.withdrawal_credentials,
randao_commitment: deposit_input.randao_commitment,
randao_layers: 0,
status: ValidatorStatus::PendingActivation,
latest_status_change_slot: state.validator_registry_latest_change_slot,
activation_slot: spec.far_future_slot,
exit_slot: spec.far_future_slot,
withdrawal_slot: spec.far_future_slot,
penalized_slot: spec.far_future_slot,
exit_count: 0,
status_flags: None,
custody_commitment: deposit_input.custody_commitment,
latest_custody_reseed_slot: 0,
penultimate_custody_reseed_slot: 0,
};
match min_empty_validator_index(state, spec) {
Some(i) => {
state.validator_registry[i] = validator;
state.validator_balances[i] = deposit_data.value;
Ok(i)
}
None => {
state.validator_registry.push(validator);
state.validator_balances.push(deposit_data.value);
Ok(state.validator_registry.len() - 1)
}
}
let _index = state.validator_registry.len();
state.validator_registry.push(validator);
state.validator_balances.push(deposit_data.value);
Ok(())
}
}
}
fn min_empty_validator_index(state: &BeaconState, spec: &ChainSpec) -> Option<usize> {
for i in 0..state.validator_registry.len() {
if state.validator_balances[i] == 0
&& state.validator_registry[i].latest_status_change_slot
+ spec.zero_balance_validator_ttl
<= state.slot
{
return Some(i);
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
@@ -125,7 +107,7 @@ mod tests {
let result = process_deposit(&mut state, &deposit, &spec);
assert_eq!(result.unwrap(), 0);
assert_eq!(result.unwrap(), ());
assert!(deposit_equals_record(
&deposit,
&state.validator_registry[0]
@@ -143,7 +125,7 @@ mod tests {
let mut deposit = get_deposit();
let result = process_deposit(&mut state, &deposit, &spec);
deposit.deposit_data.value = DEPOSIT_GWEI;
assert_eq!(result.unwrap(), i);
assert_eq!(result.unwrap(), ());
assert!(deposit_equals_record(
&deposit,
&state.validator_registry[i]
@@ -172,7 +154,7 @@ mod tests {
let result = process_deposit(&mut state, &deposit, &spec);
assert_eq!(result.unwrap(), 0);
assert_eq!(result.unwrap(), ());
assert!(deposit_equals_record(
&deposit,
&state.validator_registry[0]
@@ -182,32 +164,6 @@ mod tests {
assert_eq!(state.validator_balances.len(), 1);
}
#[test]
fn test_process_deposit_replace_validator() {
let mut state = BeaconState::default();
let spec = ChainSpec::foundation();
let mut validator = get_validator();
validator.latest_status_change_slot = 0;
state.validator_registry.push(validator);
state.validator_balances.push(0);
let mut deposit = get_deposit();
deposit.deposit_data.value = DEPOSIT_GWEI;
state.slot = spec.zero_balance_validator_ttl;
let result = process_deposit(&mut state, &deposit, &spec);
assert_eq!(result.unwrap(), 0);
assert!(deposit_equals_record(
&deposit,
&state.validator_registry[0]
));
assert_eq!(state.validator_balances[0], DEPOSIT_GWEI);
assert_eq!(state.validator_registry.len(), 1);
assert_eq!(state.validator_balances.len(), 1);
}
#[test]
fn test_process_deposit_invalid_proof_of_possession() {
let mut state = BeaconState::default();

View File

@@ -2,7 +2,8 @@ use std::cmp::min;
use honey_badger_split::SplitExt;
use spec::ChainSpec;
use types::{ShardCommittee, ValidatorRecord, ValidatorStatus};
use types::validator_registry::get_active_validator_indices;
use types::{ShardCommittee, ValidatorRecord};
use vec_shuffle::{shuffle, ShuffleErr};
type DelegatedCycle = Vec<Vec<ShardCommittee>>;
@@ -24,17 +25,7 @@ pub fn shard_and_committees_for_cycle(
spec: &ChainSpec,
) -> Result<DelegatedCycle, ValidatorAssignmentError> {
let shuffled_validator_indices = {
let validator_indices = validators
.iter()
.enumerate()
.filter_map(|(i, validator)| {
if validator.status_is(ValidatorStatus::Active) {
Some(i)
} else {
None
}
})
.collect();
let validator_indices = get_active_validator_indices(validators, 0);
shuffle(seed, validator_indices)?
};
let shard_indices: Vec<usize> = (0_usize..spec.shard_count as usize).into_iter().collect();