From c1a0df8c17faed29bc8cd8fd67c8288a0f4a20fc Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 28 Aug 2018 17:51:57 +1000 Subject: [PATCH] Implement get_new_shuffling w/o tests --- lighthouse/state/chain_config.rs | 4 + lighthouse/state/shard_and_committee.rs | 4 +- lighthouse/state/transition/mod.rs | 7 + .../state/transition/validator_allocation.rs | 145 ++++++++++++++++++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 lighthouse/state/transition/validator_allocation.rs diff --git a/lighthouse/state/chain_config.rs b/lighthouse/state/chain_config.rs index c5b244f20..3d285e7a7 100644 --- a/lighthouse/state/chain_config.rs +++ b/lighthouse/state/chain_config.rs @@ -1,11 +1,15 @@ pub struct ChainConfig { pub cycle_length: u8, + pub shard_count: u16, + pub min_committee_size: u64, } impl ChainConfig { pub fn standard() -> Self { Self { cycle_length: 8, + shard_count: 1024, + min_committee_size: 128, } } } diff --git a/lighthouse/state/shard_and_committee.rs b/lighthouse/state/shard_and_committee.rs index 788d78c4b..7f57fa6c8 100644 --- a/lighthouse/state/shard_and_committee.rs +++ b/lighthouse/state/shard_and_committee.rs @@ -1,6 +1,8 @@ + +#[derive(Clone,Debug)] pub struct ShardAndCommittee { pub shard_id: u16, - pub committee: Vec + pub committee: Vec } impl ShardAndCommittee { diff --git a/lighthouse/state/transition/mod.rs b/lighthouse/state/transition/mod.rs index 37038e49a..a79e92d06 100644 --- a/lighthouse/state/transition/mod.rs +++ b/lighthouse/state/transition/mod.rs @@ -1,8 +1,15 @@ use super::super::utils::types::Hash256; +use super::chain_config::ChainConfig; +use super::shard_and_committee::ShardAndCommittee; +use super::validator_record::ValidatorRecord; mod attestation_parent_hashes; +mod shuffling; +mod validator_allocation; pub use self::attestation_parent_hashes::attestation_parent_hashes; +pub use self::validator_allocation::get_new_shuffling; +pub use self::shuffling::shuffle; #[derive(Debug)] pub enum TransitionError { diff --git a/lighthouse/state/transition/validator_allocation.rs b/lighthouse/state/transition/validator_allocation.rs new file mode 100644 index 000000000..eb1d49413 --- /dev/null +++ b/lighthouse/state/transition/validator_allocation.rs @@ -0,0 +1,145 @@ +use super::shuffle; +use super::ChainConfig; +use super::TransitionError; +use super::ValidatorRecord; +use super::ShardAndCommittee; + +pub fn get_new_shuffling( + seed: &[u8], + validators: &Vec, + dynasty: &u64, + crosslinking_shard_start: &u16, + config: &ChainConfig) + -> Result +{ + let shuffled_validator_indices = { + let mut validator_indices = active_validator_indicies(dynasty, validators); + match shuffle(seed, validator_indices) { + Ok(shuffled) => shuffled, + _ => return Err(TransitionError::InvalidInput( + String::from("Shuffle list length exceed."))) + } + }; + let shard_indices = (0_usize..config.shard_count as usize).into_iter().collect(); + let crosslinking_shard_start = *crosslinking_shard_start as usize; + let cycle_length = config.cycle_length as usize; + let min_committee_size = config.min_committee_size as usize; + generate_cycle( + &shuffled_validator_indices, + &shard_indices, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size) +} + +/// Produce a vector of validators indicies where those +/// validators start and end dynasties are within the supplied +/// `dynasty`. +fn active_validator_indicies( + dynasty: &u64, + validators: &Vec) + -> Vec +{ + validators.iter() + .enumerate() + .filter_map(|(i, validator)| { + if (validator.start_dynasty >= *dynasty) & + (validator.end_dynasty < *dynasty) + { + Some(i) + } else { + None + } + }) + .collect() +} + +type DelegatedSlot = Vec; +type DelegatedCycle = Vec; + +fn generate_cycle( + validator_indices: &Vec, + shard_indices: &Vec, + crosslinking_shard_start: &usize, + cycle_length: &usize, + min_committee_size: &usize) + -> Result +{ + let validator_count = validator_indices.len(); + let shard_count = shard_indices.len(); + + let (committees_per_slot, slots_per_committee) = { + if validator_count >= cycle_length * min_committee_size { + let committees_per_slot = validator_count / cycle_length / (min_committee_size * 2); + let slots_per_committee = 1; + (committees_per_slot, slots_per_committee) + } else { + let committees_per_slot = 1; + let mut slots_per_committee = 1; + while (validator_count * slots_per_committee < cycle_length * min_committee_size) & + (slots_per_committee < *cycle_length) { + slots_per_committee = slots_per_committee * 2; + } + (committees_per_slot, slots_per_committee) + } + }; + + let mut cycle: DelegatedCycle = vec![]; + let split_iter = validator_indices.split(|i| i % cycle_length == 0); + for (i, slot_indices) in split_iter.enumerate() { + let shard_id_start = crosslinking_shard_start * i * committees_per_slot / slots_per_committee; + + let shard_iter = slot_indices.split(|i| i % committees_per_slot == 0); + let slot: DelegatedSlot = shard_iter + .enumerate() + .map(|(j, shard_indices)| { + ShardAndCommittee{ + shard_id: ((shard_id_start + j) % shard_count) as u16, + committee: shard_indices.to_vec(), + } + }) + .collect(); + cycle.push(slot); + }; + Ok(cycle) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn generate_cycle_helper( + validator_count: &usize, + shard_count: &usize, + crosslinking_shard_start: &usize, + cycle_length: &usize, + min_committee_size: &usize) + -> Result + { + let validator_indices = (0_usize..*validator_count).into_iter().collect(); + let shard_indices = (0_usize..*shard_count).into_iter().collect(); + generate_cycle( + &validator_indices, + &shard_indices, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size) + } + + #[test] + fn test_generate_cycle() { + let validator_count: usize = 100; + let shard_count: usize = 10; + let crosslinking_shard_start: usize = 0; + let cycle_length: usize = 20; + let min_committee_size: usize = 10; + let result = generate_cycle_helper( + &validator_count, + &shard_count, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + println!("{:?}", result); + } + +}