From 2a1433d329df8743fac83657134b7c364c05c3d8 Mon Sep 17 00:00:00 2001 From: Age Date: Wed, 3 Oct 2018 00:02:53 +1000 Subject: [PATCH 01/21] moved code from Paul's get_new_shuffling branch --- .../types/src/common/delegation/mod.rs | 25 +++ .../types/src/common/delegation/validator.rs | 206 ++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 beacon_chain/types/src/common/delegation/validator.rs diff --git a/beacon_chain/types/src/common/delegation/mod.rs b/beacon_chain/types/src/common/delegation/mod.rs index da9746f63..da75da240 100644 --- a/beacon_chain/types/src/common/delegation/mod.rs +++ b/beacon_chain/types/src/common/delegation/mod.rs @@ -1,3 +1,28 @@ mod block_hash; +mod validator; use super::utils; + +/// Produce a vector of validators indicies where those +/// validators start and end dynasties are within the supplied +/// `dynasty`. +pub 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() +} + + diff --git a/beacon_chain/types/src/common/delegation/validator.rs b/beacon_chain/types/src/common/delegation/validator.rs new file mode 100644 index 000000000..594186db5 --- /dev/null +++ b/beacon_chain/types/src/common/delegation/validator.rs @@ -0,0 +1,206 @@ +use super::active_validator_indicies; + +type DelegatedSlot = Vec; +type DelegatedCycle = Vec; + +/* + * Delegates active validators into slots for a given cycle, given a random seed. + * Returns a vector or ShardAndComitte vectors representing the shards and committiees for + * each slot. + * References get_new_shuffling (ethereum 2.1 specification) + */ +pub fn delegate_validators( + 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) +} + +/* + * Given the validator list, delegates the validators into slots and comittees for a given cycle. + */ +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) + 1; + 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 cycle = validator_indices + .chunks(validator_indices.len() / *cycle_length) + .enumerate() + .map(|(i, slot_indices)| { + let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee; + return slot_indices + .chunks(slot_indices.len() / committees_per_slot) + .enumerate() + .map(|(j, shard_indices)| { + return ShardAndCommittee{ + shard_id: ((shard_id_start + j) % shard_count) as u16, + committee: shard_indices.to_vec(), + } + }) + .collect() + }) + .collect(); + 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) + -> (Vec, Vec, Result) + { + let validator_indices = (0_usize..*validator_count).into_iter().collect(); + let shard_indices = (0_usize..*shard_count).into_iter().collect(); + let result = generate_cycle( + &validator_indices, + &shard_indices, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + (validator_indices, shard_indices, result) + } + + #[allow(dead_code)] + fn print_cycle(cycle: &DelegatedCycle) { + cycle.iter() + .enumerate() + .for_each(|(i, slot)| { + println!("slot {:?}", &i); + slot.iter() + .enumerate() + .for_each(|(i, sac)| { + println!("#{:?}\tshard_id={}\tcommittee.len()={}", + &i, &sac.shard_id, &sac.committee.len()) + }) + }); + } + + fn flatten_validators(cycle: &DelegatedCycle) + -> Vec + { + let mut flattened = vec![]; + for slot in cycle.iter() { + for sac in slot.iter() { + for validator in sac.committee.iter() { + flattened.push(*validator); + } + } + } + flattened + } + + fn flatten_and_dedup_shards(cycle: &DelegatedCycle) + -> Vec + { + let mut flattened = vec![]; + for slot in cycle.iter() { + for sac in slot.iter() { + flattened.push(sac.shard_id as usize); + } + } + flattened.dedup(); + flattened + } + + fn flatten_shards_in_slots(cycle: &DelegatedCycle) + -> Vec> + { + let mut shards_in_slots: Vec> = vec![]; + for slot in cycle.iter() { + let mut shards: Vec = vec![]; + for sac in slot.iter() { + shards.push(sac.shard_id as usize); + } + shards_in_slots.push(shards); + } + shards_in_slots + } + + + #[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 (validators, shards, result) = generate_cycle_helper( + &validator_count, + &shard_count, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + let cycle = result.unwrap(); + + let assigned_validators = flatten_validators(&cycle); + let assigned_shards = flatten_and_dedup_shards(&cycle); + let shards_in_slots = flatten_shards_in_slots(&cycle); + assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); + assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); + + let expected_shards_in_slots: Vec> = vec![ + vec![0], vec![0], // Each line is 2 slots.. + vec![1], vec![1], + vec![2], vec![2], + vec![3], vec![3], + vec![4], vec![4], + vec![5], vec![5], + vec![6], vec![6], + vec![7], vec![7], + vec![8], vec![8], + vec![9], vec![9], + ]; + // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots)); + assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.") + } +} From d15b1d066dd9d98b6342ff8024dc934830ed1c4a Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 3 Oct 2018 15:25:15 +1000 Subject: [PATCH 02/21] Create transition crate --- Cargo.toml | 1 + beacon_chain/transition/Cargo.toml | 8 + beacon_chain/transition/src/lib.rs | 9 + .../types/src/common/delegation/block_hash.rs | 62 ------ .../types/src/common/delegation/mod.rs | 28 --- .../types/src/common/delegation/validator.rs | 206 ------------------ 6 files changed, 18 insertions(+), 296 deletions(-) create mode 100644 beacon_chain/transition/Cargo.toml create mode 100644 beacon_chain/transition/src/lib.rs delete mode 100644 beacon_chain/types/src/common/delegation/block_hash.rs delete mode 100644 beacon_chain/types/src/common/delegation/mod.rs delete mode 100644 beacon_chain/types/src/common/delegation/validator.rs diff --git a/Cargo.toml b/Cargo.toml index de69506de..9f328191a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ name = "lighthouse" [workspace] members = [ "beacon_chain/types", + "beacon_chain/transition", "beacon_chain/utils/bls", "beacon_chain/utils/boolean-bitfield", "beacon_chain/utils/hashing", diff --git a/beacon_chain/transition/Cargo.toml b/beacon_chain/transition/Cargo.toml new file mode 100644 index 000000000..abf1fe6dc --- /dev/null +++ b/beacon_chain/transition/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "transition" +version = "0.1.0" +authors = ["Age Manning "] + +[dependencies] +types = { path = "../types" } +shuffling = { path = "../utils/shuffling" } diff --git a/beacon_chain/transition/src/lib.rs b/beacon_chain/transition/src/lib.rs new file mode 100644 index 000000000..a86777e9b --- /dev/null +++ b/beacon_chain/transition/src/lib.rs @@ -0,0 +1,9 @@ +extern crate types; +extern crate shuffling; + +pub mod delegation; + +#[derive(Debug)] +pub enum TransitionError { + InvalidInput(String), +} diff --git a/beacon_chain/types/src/common/delegation/block_hash.rs b/beacon_chain/types/src/common/delegation/block_hash.rs deleted file mode 100644 index 3d0939d29..000000000 --- a/beacon_chain/types/src/common/delegation/block_hash.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::utils::errors::ParameterError; -use super::utils::types::Hash256; - -/* - * Work-in-progress function: not ready for review. - */ - -pub fn get_block_hash( - active_state_recent_block_hashes: &[Hash256], - current_block_slot: u64, - slot: u64, - cycle_length: u64, // convert from standard u8 -) -> Result { - // active_state must have at 2*cycle_length hashes - assert_error!( - active_state_recent_block_hashes.len() as u64 == cycle_length * 2, - ParameterError::InvalidInput(String::from( - "active state has incorrect number of block hashes" - )) - ); - - let state_start_slot = (current_block_slot) - .checked_sub(cycle_length * 2) - .unwrap_or(0); - - assert_error!( - (state_start_slot <= slot) && (slot < current_block_slot), - ParameterError::InvalidInput(String::from("incorrect slot number")) - ); - - let index = 2 * cycle_length + slot - current_block_slot; // should always be positive - Ok(active_state_recent_block_hashes[index as usize]) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_get_block_hash() { - let block_slot: u64 = 10; - let slot: u64 = 3; - let cycle_length: u64 = 8; - - let mut block_hashes: Vec = Vec::new(); - for _i in 0..2 * cycle_length { - block_hashes.push(Hash256::random()); - } - - let result = get_block_hash( - &block_hashes, - block_slot, - slot, - cycle_length) - .unwrap(); - - assert_eq!( - result, - block_hashes[(2 * cycle_length + slot - block_slot) as usize] - ); - } -} diff --git a/beacon_chain/types/src/common/delegation/mod.rs b/beacon_chain/types/src/common/delegation/mod.rs deleted file mode 100644 index da75da240..000000000 --- a/beacon_chain/types/src/common/delegation/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -mod block_hash; -mod validator; - -use super::utils; - -/// Produce a vector of validators indicies where those -/// validators start and end dynasties are within the supplied -/// `dynasty`. -pub 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() -} - - diff --git a/beacon_chain/types/src/common/delegation/validator.rs b/beacon_chain/types/src/common/delegation/validator.rs deleted file mode 100644 index 594186db5..000000000 --- a/beacon_chain/types/src/common/delegation/validator.rs +++ /dev/null @@ -1,206 +0,0 @@ -use super::active_validator_indicies; - -type DelegatedSlot = Vec; -type DelegatedCycle = Vec; - -/* - * Delegates active validators into slots for a given cycle, given a random seed. - * Returns a vector or ShardAndComitte vectors representing the shards and committiees for - * each slot. - * References get_new_shuffling (ethereum 2.1 specification) - */ -pub fn delegate_validators( - 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) -} - -/* - * Given the validator list, delegates the validators into slots and comittees for a given cycle. - */ -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) + 1; - 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 cycle = validator_indices - .chunks(validator_indices.len() / *cycle_length) - .enumerate() - .map(|(i, slot_indices)| { - let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee; - return slot_indices - .chunks(slot_indices.len() / committees_per_slot) - .enumerate() - .map(|(j, shard_indices)| { - return ShardAndCommittee{ - shard_id: ((shard_id_start + j) % shard_count) as u16, - committee: shard_indices.to_vec(), - } - }) - .collect() - }) - .collect(); - 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) - -> (Vec, Vec, Result) - { - let validator_indices = (0_usize..*validator_count).into_iter().collect(); - let shard_indices = (0_usize..*shard_count).into_iter().collect(); - let result = generate_cycle( - &validator_indices, - &shard_indices, - &crosslinking_shard_start, - &cycle_length, - &min_committee_size); - (validator_indices, shard_indices, result) - } - - #[allow(dead_code)] - fn print_cycle(cycle: &DelegatedCycle) { - cycle.iter() - .enumerate() - .for_each(|(i, slot)| { - println!("slot {:?}", &i); - slot.iter() - .enumerate() - .for_each(|(i, sac)| { - println!("#{:?}\tshard_id={}\tcommittee.len()={}", - &i, &sac.shard_id, &sac.committee.len()) - }) - }); - } - - fn flatten_validators(cycle: &DelegatedCycle) - -> Vec - { - let mut flattened = vec![]; - for slot in cycle.iter() { - for sac in slot.iter() { - for validator in sac.committee.iter() { - flattened.push(*validator); - } - } - } - flattened - } - - fn flatten_and_dedup_shards(cycle: &DelegatedCycle) - -> Vec - { - let mut flattened = vec![]; - for slot in cycle.iter() { - for sac in slot.iter() { - flattened.push(sac.shard_id as usize); - } - } - flattened.dedup(); - flattened - } - - fn flatten_shards_in_slots(cycle: &DelegatedCycle) - -> Vec> - { - let mut shards_in_slots: Vec> = vec![]; - for slot in cycle.iter() { - let mut shards: Vec = vec![]; - for sac in slot.iter() { - shards.push(sac.shard_id as usize); - } - shards_in_slots.push(shards); - } - shards_in_slots - } - - - #[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 (validators, shards, result) = generate_cycle_helper( - &validator_count, - &shard_count, - &crosslinking_shard_start, - &cycle_length, - &min_committee_size); - let cycle = result.unwrap(); - - let assigned_validators = flatten_validators(&cycle); - let assigned_shards = flatten_and_dedup_shards(&cycle); - let shards_in_slots = flatten_shards_in_slots(&cycle); - assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); - assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); - - let expected_shards_in_slots: Vec> = vec![ - vec![0], vec![0], // Each line is 2 slots.. - vec![1], vec![1], - vec![2], vec![2], - vec![3], vec![3], - vec![4], vec![4], - vec![5], vec![5], - vec![6], vec![6], - vec![7], vec![7], - vec![8], vec![8], - vec![9], vec![9], - ]; - // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots)); - assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.") - } -} From e79a1341e9c1ae4c4a1faa86b6932e4e0882aee2 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 3 Oct 2018 15:26:41 +1000 Subject: [PATCH 03/21] add delegation logic to transition crate --- .../transition/src/delegation/block_hash.rs | 62 +++++ beacon_chain/transition/src/delegation/mod.rs | 6 + .../transition/src/delegation/validator.rs | 232 ++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 beacon_chain/transition/src/delegation/block_hash.rs create mode 100644 beacon_chain/transition/src/delegation/mod.rs create mode 100644 beacon_chain/transition/src/delegation/validator.rs diff --git a/beacon_chain/transition/src/delegation/block_hash.rs b/beacon_chain/transition/src/delegation/block_hash.rs new file mode 100644 index 000000000..3d0939d29 --- /dev/null +++ b/beacon_chain/transition/src/delegation/block_hash.rs @@ -0,0 +1,62 @@ +use super::utils::errors::ParameterError; +use super::utils::types::Hash256; + +/* + * Work-in-progress function: not ready for review. + */ + +pub fn get_block_hash( + active_state_recent_block_hashes: &[Hash256], + current_block_slot: u64, + slot: u64, + cycle_length: u64, // convert from standard u8 +) -> Result { + // active_state must have at 2*cycle_length hashes + assert_error!( + active_state_recent_block_hashes.len() as u64 == cycle_length * 2, + ParameterError::InvalidInput(String::from( + "active state has incorrect number of block hashes" + )) + ); + + let state_start_slot = (current_block_slot) + .checked_sub(cycle_length * 2) + .unwrap_or(0); + + assert_error!( + (state_start_slot <= slot) && (slot < current_block_slot), + ParameterError::InvalidInput(String::from("incorrect slot number")) + ); + + let index = 2 * cycle_length + slot - current_block_slot; // should always be positive + Ok(active_state_recent_block_hashes[index as usize]) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_block_hash() { + let block_slot: u64 = 10; + let slot: u64 = 3; + let cycle_length: u64 = 8; + + let mut block_hashes: Vec = Vec::new(); + for _i in 0..2 * cycle_length { + block_hashes.push(Hash256::random()); + } + + let result = get_block_hash( + &block_hashes, + block_slot, + slot, + cycle_length) + .unwrap(); + + assert_eq!( + result, + block_hashes[(2 * cycle_length + slot - block_slot) as usize] + ); + } +} diff --git a/beacon_chain/transition/src/delegation/mod.rs b/beacon_chain/transition/src/delegation/mod.rs new file mode 100644 index 000000000..2bc9bccd2 --- /dev/null +++ b/beacon_chain/transition/src/delegation/mod.rs @@ -0,0 +1,6 @@ +use super::types; +use super::TransitionError; +use super::shuffling::shuffle; + +// mod block_hash; +pub mod validator; diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs new file mode 100644 index 000000000..426b1a5e3 --- /dev/null +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -0,0 +1,232 @@ +use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig}; +use super::TransitionError; +use super::shuffle; + +type DelegatedSlot = Vec; +type DelegatedCycle = Vec; + + +/* 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() +} + + +/* + * Delegates active validators into slots for a given cycle, given a random seed. + * Returns a vector or ShardAndComitte vectors representing the shards and committiees for + * each slot. + * References get_new_shuffling (ethereum 2.1 specification) + */ +pub fn delegate_validators( + 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) +} + +/* + * Given the validator list, delegates the validators into slots and comittees for a given cycle. + */ +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) + 1; + 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 cycle = validator_indices + .chunks(validator_indices.len() / *cycle_length) + .enumerate() + .map(|(i, slot_indices)| { + let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee; + return slot_indices + .chunks(slot_indices.len() / committees_per_slot) + .enumerate() + .map(|(j, shard_indices)| { + return ShardAndCommittee{ + shard_id: ((shard_id_start + j) % shard_count) as u16, + committee: shard_indices.to_vec(), + } + }) + .collect() + }) + .collect(); + 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) + -> (Vec, Vec, Result) + { + let validator_indices = (0_usize..*validator_count).into_iter().collect(); + let shard_indices = (0_usize..*shard_count).into_iter().collect(); + let result = generate_cycle( + &validator_indices, + &shard_indices, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + (validator_indices, shard_indices, result) + } + + #[allow(dead_code)] + fn print_cycle(cycle: &DelegatedCycle) { + cycle.iter() + .enumerate() + .for_each(|(i, slot)| { + println!("slot {:?}", &i); + slot.iter() + .enumerate() + .for_each(|(i, sac)| { + println!("#{:?}\tshard_id={}\tcommittee.len()={}", + &i, &sac.shard_id, &sac.committee.len()) + }) + }); + } + + fn flatten_validators(cycle: &DelegatedCycle) + -> Vec + { + let mut flattened = vec![]; + for slot in cycle.iter() { + for sac in slot.iter() { + for validator in sac.committee.iter() { + flattened.push(*validator); + } + } + } + flattened + } + + fn flatten_and_dedup_shards(cycle: &DelegatedCycle) + -> Vec + { + let mut flattened = vec![]; + for slot in cycle.iter() { + for sac in slot.iter() { + flattened.push(sac.shard_id as usize); + } + } + flattened.dedup(); + flattened + } + + fn flatten_shards_in_slots(cycle: &DelegatedCycle) + -> Vec> + { + let mut shards_in_slots: Vec> = vec![]; + for slot in cycle.iter() { + let mut shards: Vec = vec![]; + for sac in slot.iter() { + shards.push(sac.shard_id as usize); + } + shards_in_slots.push(shards); + } + shards_in_slots + } + + + #[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 (validators, shards, result) = generate_cycle_helper( + &validator_count, + &shard_count, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + let cycle = result.unwrap(); + + let assigned_validators = flatten_validators(&cycle); + let assigned_shards = flatten_and_dedup_shards(&cycle); + let shards_in_slots = flatten_shards_in_slots(&cycle); + assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); + assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); + + let expected_shards_in_slots: Vec> = vec![ + vec![0], vec![0], // Each line is 2 slots.. + vec![1], vec![1], + vec![2], vec![2], + vec![3], vec![3], + vec![4], vec![4], + vec![5], vec![5], + vec![6], vec![6], + vec![7], vec![7], + vec![8], vec![8], + vec![9], vec![9], + ]; + // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots)); + assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.") + } +} From 57e3f8c4653a9ba2f334d59d41de219b7cb86fec Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 3 Oct 2018 15:41:04 +1000 Subject: [PATCH 04/21] Correct get_new_shuffling. Closes #25 --- beacon_chain/transition/src/delegation/validator.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 426b1a5e3..760b6bab7 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -1,6 +1,7 @@ use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig}; use super::TransitionError; use super::shuffle; +use std::cmp::min; type DelegatedSlot = Vec; type DelegatedCycle = Vec; @@ -79,7 +80,9 @@ fn generate_cycle( 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) + 1; + let committees_per_slot = min(validator_count / cycle_length / + (min_committee_size * 2) + 1, shard_count / + cycle_length); let slots_per_committee = 1; (committees_per_slot, slots_per_committee) } else { From 229351b38ec8988d8289d5dcdfa43d8d82d35e17 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 3 Oct 2018 18:47:18 +1000 Subject: [PATCH 05/21] Adds list splitting function and begins delegation testing --- .../transition/src/delegation/validator.rs | 61 +++++++++++++++++++ beacon_chain/types/src/chain_config.rs | 14 +++++ 2 files changed, 75 insertions(+) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 760b6bab7..0dc0d5f16 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -29,6 +29,19 @@ fn active_validator_indicies( .collect() } +/* + * splits a vector into chunks of size n. All postive n values are applicable, + * hence the honey_badger prefix. + */ +fn honey_badger_split(list: &Vec, n: usize) -> Vec> { + let mut split_list: Vec> = vec![]; + let list_length = list.len(); + for i in 0..n { + let partition = list.get(list_length*i/n..list_length*(i+1)/n).unwrap(); // cannot go out of bounds + split_list.push(partition.to_vec()); + } + split_list +} /* * Delegates active validators into slots for a given cycle, given a random seed. @@ -75,9 +88,17 @@ fn generate_cycle( min_committee_size: &usize) -> Result { + let validator_count = validator_indices.len(); let shard_count = shard_indices.len(); + if shard_count / cycle_length == 0 { + return Err(TransitionError::InvalidInput(String::from("Number of + shards needs to be greater than + cycle length"))); + + } + let (committees_per_slot, slots_per_committee) = { if validator_count >= cycle_length * min_committee_size { let committees_per_slot = min(validator_count / cycle_length / @@ -217,6 +238,46 @@ mod tests { assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); + let expected_shards_in_slots: Vec> = vec![ + vec![0], vec![0], // Each line is 2 slots.. + vec![1], vec![1], + vec![2], vec![2], + vec![3], vec![3], + vec![4], vec![4], + vec![5], vec![5], + vec![6], vec![6], + vec![7], vec![7], + vec![8], vec![8], + vec![9], vec![9], + ]; + // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots)); + assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.") + } + + #[test] + // Check that the committees per slot is upper bounded by shard count + fn test_generate_cycle_committees_bounded() { + let validator_count: usize = 101; + let shard_count: usize = 15; + let crosslinking_shard_start: usize = 0; + let cycle_length: usize = 10; + let min_committee_size: usize = 10; + let (validators, shards, result) = generate_cycle_helper( + &validator_count, + &shard_count, + &crosslinking_shard_start, + &cycle_length, + &min_committee_size); + let cycle = result.unwrap(); + + let assigned_validators = flatten_validators(&cycle); + let assigned_shards = flatten_and_dedup_shards(&cycle); + let shards_in_slots = flatten_shards_in_slots(&cycle); + print_cycle(&cycle); + assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); + assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); + + let expected_shards_in_slots: Vec> = vec![ vec![0], vec![0], // Each line is 2 slots.. vec![1], vec![1], diff --git a/beacon_chain/types/src/chain_config.rs b/beacon_chain/types/src/chain_config.rs index 750081aad..4cdc91a6d 100644 --- a/beacon_chain/types/src/chain_config.rs +++ b/beacon_chain/types/src/chain_config.rs @@ -20,6 +20,20 @@ impl ChainConfig { } } + pub fn validate(&self) -> bool { + // criteria that ensure the config is valid + + // shard_count / cycle_length > 0 otherwise validator delegation + // will fail. + if self.shard_count / self.cycle_length as u16 == 0 { + return false; + } + + true + } + + + #[cfg(test)] pub fn super_fast_tests() -> Self { Self { From c8d5f00d7cad7b11ce1d17479f290b8016471f25 Mon Sep 17 00:00:00 2001 From: Age Date: Wed, 3 Oct 2018 21:57:21 +1000 Subject: [PATCH 06/21] Improve split function --- beacon_chain/transition/src/delegation/validator.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 0dc0d5f16..9c6019d72 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -37,7 +37,10 @@ fn honey_badger_split(list: &Vec, n: usize) -> Vec> { let mut split_list: Vec> = vec![]; let list_length = list.len(); for i in 0..n { - let partition = list.get(list_length*i/n..list_length*(i+1)/n).unwrap(); // cannot go out of bounds + let partition = match list.get(list_length*i/n..list_length*(i+1)/n) { + Some(v) => v, + None => unreachable!(), + }; split_list.push(partition.to_vec()); } split_list From 874a0babbb0f48717344e9bb9759bf54e7c10991 Mon Sep 17 00:00:00 2001 From: Age Date: Wed, 3 Oct 2018 23:37:54 +1000 Subject: [PATCH 07/21] Converts split function into an iterable trait --- .../transition/src/delegation/validator.rs | 76 +++++++++++++------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 9c6019d72..95f1a47df 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -6,6 +6,54 @@ use std::cmp::min; type DelegatedSlot = Vec; type DelegatedCycle = Vec; +/* + * Iterator for the honey_badger_split function + */ +struct Split<'a, T: 'a> { + n: usize, + current_pos: usize, + list: &'a [T], + list_length: usize +} + +impl<'a,T> Iterator for Split<'a, T> { + type Item = &'a [T]; + + fn next(&mut self) -> Option { + self.current_pos +=1; + if self.current_pos <= self.n { + match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) { + Some(v) => Some(v), + None => unreachable!() + } + } + else { + None + } + } +} + +/* + * splits a slice into chunks of size n. All postive n values are applicable, + * hence the honey_badger prefix. + * Returns an iterator over the original list. + */ +trait SplitExt { + fn honey_badger_split(&self, n: usize) -> Split; +} + +impl SplitExt for [T] { + + fn honey_badger_split(&self, n: usize) -> Split { + Split { + n: n, + current_pos: 0, + list: &self, + list_length: self.len(), + } + } +} + /* Produce a vector of validators indicies where those validators start and end * dynasties are within the supplied `dynasty`. @@ -29,23 +77,6 @@ fn active_validator_indicies( .collect() } -/* - * splits a vector into chunks of size n. All postive n values are applicable, - * hence the honey_badger prefix. - */ -fn honey_badger_split(list: &Vec, n: usize) -> Vec> { - let mut split_list: Vec> = vec![]; - let list_length = list.len(); - for i in 0..n { - let partition = match list.get(list_length*i/n..list_length*(i+1)/n) { - Some(v) => v, - None => unreachable!(), - }; - split_list.push(partition.to_vec()); - } - split_list -} - /* * Delegates active validators into slots for a given cycle, given a random seed. * Returns a vector or ShardAndComitte vectors representing the shards and committiees for @@ -120,13 +151,11 @@ fn generate_cycle( } }; - let cycle = validator_indices - .chunks(validator_indices.len() / *cycle_length) + let cycle = validator_indices.honey_badger_split(*cycle_length) .enumerate() .map(|(i, slot_indices)| { let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee; - return slot_indices - .chunks(slot_indices.len() / committees_per_slot) + return slot_indices.honey_badger_split(committees_per_slot) .enumerate() .map(|(j, shard_indices)| { return ShardAndCommittee{ @@ -260,7 +289,7 @@ mod tests { #[test] // Check that the committees per slot is upper bounded by shard count fn test_generate_cycle_committees_bounded() { - let validator_count: usize = 101; + let validator_count: usize = 1001; let shard_count: usize = 15; let crosslinking_shard_start: usize = 0; let cycle_length: usize = 10; @@ -272,11 +301,10 @@ mod tests { &cycle_length, &min_committee_size); let cycle = result.unwrap(); - + print_cycle(&cycle); let assigned_validators = flatten_validators(&cycle); let assigned_shards = flatten_and_dedup_shards(&cycle); let shards_in_slots = flatten_shards_in_slots(&cycle); - print_cycle(&cycle); assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); From 1858b2d32bcdd040948912f37f8b5d45e0c52635 Mon Sep 17 00:00:00 2001 From: Age Date: Thu, 4 Oct 2018 13:21:16 +1000 Subject: [PATCH 08/21] Corrects cycle tests --- .../transition/src/delegation/validator.rs | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 95f1a47df..45331c4c8 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -248,11 +248,11 @@ mod tests { shards_in_slots } - + // TODO: Improve these tests to check committee lengths #[test] fn test_generate_cycle() { let validator_count: usize = 100; - let shard_count: usize = 10; + let shard_count: usize = 20; let crosslinking_shard_start: usize = 0; let cycle_length: usize = 20; let min_committee_size: usize = 10; @@ -267,8 +267,9 @@ mod tests { let assigned_validators = flatten_validators(&cycle); let assigned_shards = flatten_and_dedup_shards(&cycle); let shards_in_slots = flatten_shards_in_slots(&cycle); + let expected_shards = shards.get(0..10).unwrap(); assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); - assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); + assert_eq!(assigned_shards, expected_shards, "Shard assignment incorrect"); let expected_shards_in_slots: Vec> = vec![ vec![0], vec![0], // Each line is 2 slots.. @@ -289,11 +290,11 @@ mod tests { #[test] // Check that the committees per slot is upper bounded by shard count fn test_generate_cycle_committees_bounded() { - let validator_count: usize = 1001; - let shard_count: usize = 15; + let validator_count: usize = 523; + let shard_count: usize = 31; let crosslinking_shard_start: usize = 0; - let cycle_length: usize = 10; - let min_committee_size: usize = 10; + let cycle_length: usize = 11; + let min_committee_size: usize = 5; let (validators, shards, result) = generate_cycle_helper( &validator_count, &shard_count, @@ -301,26 +302,14 @@ mod tests { &cycle_length, &min_committee_size); let cycle = result.unwrap(); - print_cycle(&cycle); let assigned_validators = flatten_validators(&cycle); let assigned_shards = flatten_and_dedup_shards(&cycle); let shards_in_slots = flatten_shards_in_slots(&cycle); + let expected_shards = shards.get(0..22).unwrap(); + let expected_shards_in_slots: Vec> = + (0_usize..11_usize) .map(|x| vec![2*x,2*x+1]).collect(); assert_eq!(assigned_validators, validators, "Validator assignment incorrect"); - assert_eq!(assigned_shards, shards, "Shard assignment incorrect"); - - - let expected_shards_in_slots: Vec> = vec![ - vec![0], vec![0], // Each line is 2 slots.. - vec![1], vec![1], - vec![2], vec![2], - vec![3], vec![3], - vec![4], vec![4], - vec![5], vec![5], - vec![6], vec![6], - vec![7], vec![7], - vec![8], vec![8], - vec![9], vec![9], - ]; + assert_eq!(assigned_shards, expected_shards, "Shard assignment incorrect"); // assert!(compare_shards_in_slots(&cycle, &expected_shards_in_slots)); assert_eq!(expected_shards_in_slots, shards_in_slots, "Shard assignment incorrect.") } From fd01ffc2a1922a9979e09b868cfe8171666959f2 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Fri, 5 Oct 2018 14:51:16 +1000 Subject: [PATCH 09/21] Removes block_hash.rs and adds minor clippy fixes --- .../transition/src/delegation/block_hash.rs | 62 ------------------- beacon_chain/transition/src/delegation/mod.rs | 1 - .../transition/src/delegation/validator.rs | 62 +++++++++---------- 3 files changed, 29 insertions(+), 96 deletions(-) delete mode 100644 beacon_chain/transition/src/delegation/block_hash.rs diff --git a/beacon_chain/transition/src/delegation/block_hash.rs b/beacon_chain/transition/src/delegation/block_hash.rs deleted file mode 100644 index 3d0939d29..000000000 --- a/beacon_chain/transition/src/delegation/block_hash.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::utils::errors::ParameterError; -use super::utils::types::Hash256; - -/* - * Work-in-progress function: not ready for review. - */ - -pub fn get_block_hash( - active_state_recent_block_hashes: &[Hash256], - current_block_slot: u64, - slot: u64, - cycle_length: u64, // convert from standard u8 -) -> Result { - // active_state must have at 2*cycle_length hashes - assert_error!( - active_state_recent_block_hashes.len() as u64 == cycle_length * 2, - ParameterError::InvalidInput(String::from( - "active state has incorrect number of block hashes" - )) - ); - - let state_start_slot = (current_block_slot) - .checked_sub(cycle_length * 2) - .unwrap_or(0); - - assert_error!( - (state_start_slot <= slot) && (slot < current_block_slot), - ParameterError::InvalidInput(String::from("incorrect slot number")) - ); - - let index = 2 * cycle_length + slot - current_block_slot; // should always be positive - Ok(active_state_recent_block_hashes[index as usize]) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_get_block_hash() { - let block_slot: u64 = 10; - let slot: u64 = 3; - let cycle_length: u64 = 8; - - let mut block_hashes: Vec = Vec::new(); - for _i in 0..2 * cycle_length { - block_hashes.push(Hash256::random()); - } - - let result = get_block_hash( - &block_hashes, - block_slot, - slot, - cycle_length) - .unwrap(); - - assert_eq!( - result, - block_hashes[(2 * cycle_length + slot - block_slot) as usize] - ); - } -} diff --git a/beacon_chain/transition/src/delegation/mod.rs b/beacon_chain/transition/src/delegation/mod.rs index 2bc9bccd2..265b3e9b6 100644 --- a/beacon_chain/transition/src/delegation/mod.rs +++ b/beacon_chain/transition/src/delegation/mod.rs @@ -2,5 +2,4 @@ use super::types; use super::TransitionError; use super::shuffling::shuffle; -// mod block_hash; pub mod validator; diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 45331c4c8..41c4c0e4d 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -3,12 +3,9 @@ use super::TransitionError; use super::shuffle; use std::cmp::min; -type DelegatedSlot = Vec; -type DelegatedCycle = Vec; +type DelegatedCycle = Vec>; -/* - * Iterator for the honey_badger_split function - */ +/// Iterator for the honey_badger_split function struct Split<'a, T: 'a> { n: usize, current_pos: usize, @@ -33,11 +30,10 @@ impl<'a,T> Iterator for Split<'a, T> { } } -/* - * splits a slice into chunks of size n. All postive n values are applicable, - * hence the honey_badger prefix. - * Returns an iterator over the original list. - */ + +/// splits a slice into chunks of size n. All postive n values are applicable, +/// hence the honey_badger prefix. +/// Returns an iterator over the original list. trait SplitExt { fn honey_badger_split(&self, n: usize) -> Split; } @@ -46,7 +42,7 @@ impl SplitExt for [T] { fn honey_badger_split(&self, n: usize) -> Split { Split { - n: n, + n, current_pos: 0, list: &self, list_length: self.len(), @@ -59,15 +55,15 @@ impl SplitExt for [T] { * dynasties are within the supplied `dynasty`. */ fn active_validator_indicies( - dynasty: &u64, - validators: &Vec) + dynasty: u64, + validators: &[ValidatorRecord]) -> Vec { validators.iter() .enumerate() .filter_map(|(i, validator)| { - if (validator.start_dynasty >= *dynasty) & - (validator.end_dynasty < *dynasty) + if (validator.start_dynasty >= dynasty) & + (validator.end_dynasty < dynasty) { Some(i) } else { @@ -85,9 +81,9 @@ fn active_validator_indicies( */ pub fn delegate_validators( seed: &[u8], - validators: &Vec, - dynasty: &u64, - crosslinking_shard_start: &u16, + validators: &[ValidatorRecord], + dynasty: u64, + crosslinking_shard_start: u16, config: &ChainConfig) -> Result { @@ -99,27 +95,27 @@ pub fn delegate_validators( 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 shard_indices: Vec = (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) + crosslinking_shard_start, + cycle_length, + min_committee_size) } /* * Given the validator list, delegates the validators into slots and comittees for a given cycle. */ fn generate_cycle( - validator_indices: &Vec, - shard_indices: &Vec, - crosslinking_shard_start: &usize, - cycle_length: &usize, - min_committee_size: &usize) + validator_indices: &[usize], + shard_indices: &[usize], + crosslinking_shard_start: usize, + cycle_length: usize, + min_committee_size: usize) -> Result { @@ -144,21 +140,21 @@ fn generate_cycle( 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; + (slots_per_committee < cycle_length) { + slots_per_committee *= 2; } (committees_per_slot, slots_per_committee) } }; - let cycle = validator_indices.honey_badger_split(*cycle_length) + let cycle = validator_indices.honey_badger_split(cycle_length) .enumerate() .map(|(i, slot_indices)| { let shard_id_start = crosslinking_shard_start + i * committees_per_slot / slots_per_committee; - return slot_indices.honey_badger_split(committees_per_slot) + slot_indices.honey_badger_split(committees_per_slot) .enumerate() .map(|(j, shard_indices)| { - return ShardAndCommittee{ + ShardAndCommittee{ shard_id: ((shard_id_start + j) % shard_count) as u16, committee: shard_indices.to_vec(), } From 14e12db374f3ae6b4741f4c79239302686351b09 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Fri, 5 Oct 2018 14:53:21 +1000 Subject: [PATCH 10/21] Updates validation tests for clippy modifications --- .../transition/src/delegation/validator.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 41c4c0e4d..b745fa3f4 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -172,19 +172,19 @@ mod tests { fn generate_cycle_helper( validator_count: &usize, shard_count: &usize, - crosslinking_shard_start: &usize, - cycle_length: &usize, - min_committee_size: &usize) + crosslinking_shard_start: usize, + cycle_length: usize, + min_committee_size: usize) -> (Vec, Vec, Result) { - let validator_indices = (0_usize..*validator_count).into_iter().collect(); - let shard_indices = (0_usize..*shard_count).into_iter().collect(); + let validator_indices: Vec = (0_usize..*validator_count).into_iter().collect(); + let shard_indices: Vec = (0_usize..*shard_count).into_iter().collect(); let result = generate_cycle( &validator_indices, &shard_indices, - &crosslinking_shard_start, - &cycle_length, - &min_committee_size); + crosslinking_shard_start, + cycle_length, + min_committee_size); (validator_indices, shard_indices, result) } @@ -255,9 +255,9 @@ mod tests { let (validators, shards, result) = generate_cycle_helper( &validator_count, &shard_count, - &crosslinking_shard_start, - &cycle_length, - &min_committee_size); + crosslinking_shard_start, + cycle_length, + min_committee_size); let cycle = result.unwrap(); let assigned_validators = flatten_validators(&cycle); @@ -294,9 +294,9 @@ mod tests { let (validators, shards, result) = generate_cycle_helper( &validator_count, &shard_count, - &crosslinking_shard_start, - &cycle_length, - &min_committee_size); + crosslinking_shard_start, + cycle_length, + min_committee_size); let cycle = result.unwrap(); let assigned_validators = flatten_validators(&cycle); let assigned_shards = flatten_and_dedup_shards(&cycle); From 8abea8670237731e3ce967bebd7e8cba0b1bc30b Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Tue, 9 Oct 2018 18:16:19 +1100 Subject: [PATCH 11/21] Made a series of updates, typo fixes, and rewordings to the README. --- README.md | 203 +++++++++++++++++++++++++++--------------------------- 1 file changed, 102 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 01ce24b59..9d9dd536e 100644 --- a/README.md +++ b/README.md @@ -14,146 +14,147 @@ This readme is split into two major sections: - [What is Ethereum 2.0](#what-is-ethereum-20): an introduction to Ethereum 2.0. If you'd like some background on Sigma Prime, please see the [Lighthouse Update -\#00](https://lighthouse.sigmaprime.io/update-00.html) blog post or our -[website](https://sigmaprime.io). +\#00](https://lighthouse.sigmaprime.io/update-00.html) blog post or the +[company website](https://sigmaprime.io). ## Lighthouse Client -Lighthouse is an open-source Ethereum 2.0 client, in development. Designed as -an Ethereum 2.0-only client, Lighthouse will not re-implement the existing +Lighthouse is an open-source Ethereum 2.0 client that is currently under development. +Designed as an Ethereum 2.0-only client, Lighthouse will not re-implement the existing proof-of-work protocol. Maintaining a forward-focus on Ethereum 2.0 ensures -that Lighthouse will avoid reproducing the high-quality work already undertaken -by existing clients. For present-Ethereum functionality, Lighthouse will -connect to existing clients like +that Lighthouse avoids reproducing the high-quality work already undertaken +by existing projects. As such, Lighthouse will +connect to existing clients, such as [Geth](https://github.com/ethereum/go-ethereum) or -[Parity-Ethereum](https://github.com/paritytech/parity-ethereum) via RPC. +[Parity-Ethereum](https://github.com/paritytech/parity-ethereum), via RPC to enable +present-Ethereum functionality. ### Goals -We aim to contribute to the research and development of a secure, efficient and -decentralised Ethereum protocol through the development of an open-source +The purpose of this project is to further research and development towards a secure, +efficient, and decentralized Ethereum protocol, facilitated by a new open-source Ethereum 2.0 client. -In addition to building an implementation, we seek to help maintain and improve -the protocol wherever possible. +In addition to implementing a new client, the project seeks to maintain and improve +the Ethereum protocol wherever possible. ### Components The following list describes some of the components actively under development by the team: -- **BLS cryptography**: we presently use the [Apache +- **BLS cryptography**: Lighthouse presently use the [Apache Milagro](https://milagro.apache.org/) cryptography library to create and verify BLS aggregate signatures. BLS signatures are core to Eth 2.0 as they allow the signatures of many validators to be compressed into a constant 96 -bytes and verified efficiently.. We're presently maintaining our own [BLS +bytes and efficiently verified. The Lighthouse project is presently maintaining its own [BLS aggregates library](https://github.com/sigp/signature-schemes), gratefully -forked from @lovesh. -- **DoS-resistant block pre-processing**: processing blocks in proof-of-stake +forked from [@lovesh](https://github.com/lovesh). +- **DoS-resistant block pre-processing**: Processing blocks in proof-of-stake is more resource intensive than proof-of-work. As such, clients need to -ensure that bad blocks can be rejected as efficiently as possible. We can -presently process a block with 10 million ETH staked in 0.006 seconds and -reject invalid blocks even quicker. See the -[issue](https://github.com/ethereum/beacon_chain/issues/103) on -[ethereum/beacon_chain](https://github.com/ethereum/beacon_chain) +ensure that bad blocks can be rejected as efficiently as possible. At present, +blocks having 10 million ETH staked can be processed in 0.006 seconds, and +invalid blocks are rejected even more quickly. See +[issue #103](https://github.com/ethereum/beacon_chain/issues/103) on +[ethereum/beacon_chain](https://github.com/ethereum/beacon_chain). . - **P2P networking**: Eth 2.0 will likely use the [libp2p framework](https://libp2p.io/). Lighthouse aims to work alongside -[Parity](https://www.parity.io/) to get -[libp2p-rust](https://github.com/libp2p/rust-libp2p) fit-for-purpose. -- **Validator duties** : the project involves the development of "validator" - services for users who wish to stake ETH. To fulfil their duties, validators -require a consistent view of the chain and the ability to vote upon both shard -and beacon chain blocks.. -- **New serialization formats**: lighthouse is working alongside EF researchers - to develop "simpleserialize" a purpose-built serialization format for sending -information across the network. Check out our [SSZ +[Parity](https://www.parity.io/) to ensure +[libp2p-rust](https://github.com/libp2p/rust-libp2p) is fit-for-purpose. +- **Validator duties** : The project involves development of "validator + services" for users who wish to stake ETH. To fulfill their duties, validators +require a consistent view of the chain and the ability to vote upon blocks from both shard +and beacon chains. +- **New serialization formats**: Lighthouse is working alongside researchers from the Ethereum Foundation + to develop *simpleserialize*, a purpose-built serialization format for sending +information across a network. Check out the [SSZ implementation](https://github.com/sigp/lighthouse/tree/master/beacon_chain/utils/ssz) -and our +and this [research](https://github.com/sigp/serialization_sandbox/blob/report/report/serialization_report.md) -on serialization formats. -- **Casper FFG fork-choice**: the [Casper +on serialization formats for more information. +- **Casper FFG fork-choice**: The [Casper FFG](https://arxiv.org/abs/1710.09437) fork-choice rules allow the chain to select a canonical chain in the case of a fork. -- **Efficient state transition logic**: "state transition" logic governs - updates to the validator set as validators log in/out, penalises/rewards +- **Efficient state transition logic**: State transition logic governs + updates to the validator set as validators log in/out, penalizes/rewards validators, rotates validators across shards, and implements other core tasks. -- **Fuzzing and testing environments**: we are preparing to implement lab -environments with CI work-flows to provide automated security analysis.. +- **Fuzzing and testing environments**: Implementation of lab +environments with continuous integration (CI) workflows, providing automated security analysis. -In addition to these components we're also working on database schemas, RPC +In addition to these components we are also working on database schemas, RPC frameworks, specification development, database optimizations (e.g., -bloom-filters) and tons of other interesting stuff (at least we think so). +bloom-filters), and tons of other interesting stuff (at least we think so). ### Contributing **Lighthouse welcomes contributors with open-arms.** -Layer-1 infrastructure is a critical component of the ecosystem and relies -heavily on community contribution. Building Ethereum 2.0 is a huge task and we +Layer-1 infrastructure is a critical component for the ecosystem and relies +heavily on contributions from the community. Building Ethereum 2.0 is a huge task and we refuse to conduct an inappropriate ICO or charge licensing fees. Instead, we fund development through grants and support from Sigma Prime. If you would like to learn more about Ethereum 2.0 and/or -[Rust](https://www.rust-lang.org/), we would be more than happy to on-board you -and assign you to some tasks. We aim to be as accepting and understanding as +[Rust](https://www.rust-lang.org/), we are more than happy to on-board you +and assign you some tasks. We aim to be as accepting and understanding as possible; we are more than happy to up-skill contributors in exchange for their -help on the project. +assistance with the project. -Alternatively, if you an ETH/Rust veteran we'd love to have your input. We're -always looking for the best way to implement things and will consider any -respectful criticism. +Alternatively, if you are an ETH/Rust veteran, we'd love your input. We're +always looking for the best way to implement things and welcome all +respectful criticisms. If you'd like to contribute, try having a look through the [open issues](https://github.com/sigp/lighthouse/issues) (tip: look for the [good first issue](https://github.com/sigp/lighthouse/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) -tag) and ping us on the [gitter](https://gitter.im/sigp/lighthouse). We need +tag) and ping us on the [gitter](https://gitter.im/sigp/lighthouse) channel. We need your support! ### Running -**NOTE: the cryptography libraries used in this implementation are -experimental and as such all cryptography should be assumed to be insecure.** +**NOTE: The cryptography libraries used in this implementation are +experimental. As such all cryptography is assumed to be insecure.** -The code-base is still under-development and does not provide any user-facing -functionality. For developers and researchers, there are tests and benchmarks -which could be of interest. +This code-base is still very much under-development and does not provide any user-facing +functionality. For developers and researchers, there are several tests and benchmarks +which may be of interest. -To run tests, use +To run tests, use: ``` $ cargo test --all ``` -To run benchmarks, use +To run benchmarks, use: ``` $ cargo bench --all ``` -Lighthouse presently runs on Rust `stable`, however, benchmarks require the +Lighthouse presently runs on Rust `stable`, however, benchmarks currently require the `nightly` version. ### Engineering Ethos -Lighthouse aims to produce many small, easily-tested components, each separated +Lighthouse aims to produce many small easily-tested components, each separated into individual crates wherever possible. Generally, tests can be kept in the same file, as is typical in Rust. -Integration tests should be placed in the `tests` directory in the crates root. -Particularity large (line-count) tests should be separated into another file. +Integration tests should be placed in the `tests` directory in the crate's root. +Particularity large (line-count) tests should be placed into a separate file. -A function is not complete until it is tested. We produce tests to protect -against regression (accidentally breaking things) and to help those who read -our code to understand how the function should (or shouldn't) be used. +A function is not considered complete until a test exists for it. We produce tests to protect +against regression (accidentally breaking things) and to provide examples that +help readers of the code base understand how functions should (or should not) be used. -Each PR is to be reviewed by at-least one "core developer" (i.e., someone with -write-access to the repository). This helps to detect bugs, improve consistency -and relieves any one individual of the responsibility of an error. +Each pull request is to be reviewed by at least one "core developer" (i.e., someone with +write-access to the repository). This helps to ensure bugs are detected, consistency is maintained, +and responsibility of errors is dispersed. -Discussion should be respectful and intellectual. Have fun, make jokes but -respect other people's limits. +Discussion must be respectful and intellectual. Have fun and make jokes, but +always respect the limits of other people. ### Directory Structure @@ -164,30 +165,30 @@ Here we provide an overview of the directory structure: validation, BLS crypto, etc. - `\lighthouse`: contains logic specific to this client implementation. E.g., CLI parsing, RPC end-points, databases, etc. -- `\network-libp2p`: contains a proof-of-concept libp2p implementation. Will be +- `\network-libp2p`: contains a proof-of-concept libp2p implementation. This component will be replaced once research around p2p has been finalized. ## Contact -The best place for discussion is the [sigp/lighthouse](https://gitter.im/sigp/lighthouse) gitter. +The best place for discussion is the [sigp/lighthouse gitter](https://gitter.im/sigp/lighthouse). Ping @paulhauner or @AgeManning to get the quickest response. # What is Ethereum 2.0 -Ethereum 2.0 refers to a new blockchain currently under development +Ethereum 2.0 refers to a new blockchain system currently under development by the Ethereum Foundation and the Ethereum community. The Ethereum 2.0 blockchain -consists of 1,025 proof-of-stake blockchains; the "beacon chain" and 1,024 +consists of 1,025 proof-of-stake blockchains. This includes the "beacon chain" and 1,024 "shard chains". ## Beacon Chain -The Beacon Chain differs from existing blockchains such as Bitcoin and -Ethereum, in that it doesn't process "transactions", per say. Instead, it -maintains a set of bonded (staked) validators and co-ordinates these to provide -services to a static set of "sub-blockchains" (shards). These shards process -normal transactions, such as "5 ETH from A to B", in parallel whilst deferring -consensus to the Beacon Chain. +The concept of a beacon chain differs from existing blockchains, such as Bitcoin and +Ethereum, in that it doesn't process transactions per se. Instead, it +maintains a set of bonded (staked) validators and coordinates these to provide +services to a static set of *sub-blockchains* (i.e. shards). Each of these shard blockchains +processes normal transactions (e.g. "Transfer 5 ETH from A to B") in parallel whilst deferring +consensus mechanisms to the beacon chain. Major services provided by the beacon chain to its shards include the following: @@ -195,53 +196,53 @@ Major services provided by the beacon chain to its shards include the following: scheme](https://ethresear.ch/t/minimal-vdf-randomness-beacon/3566). - Validator management, including: - Inducting and ejecting validators. - - Delegating randomly-shuffled subsets of validators to validate shards. - - Penalising and rewarding validators. + - Assigning randomly-shuffled subsets of validators to particular shards. + - Penalizing and rewarding validators. - Proof-of-stake consensus for shard chain blocks. ## Shard Chains -Shards can be thought of like CPU cores - they're a lane where transactions can +Shards are analogous to CPU cores - they're a resource where transactions can execute in series (one-after-another). Presently, Ethereum is single-core and -can only _fully_ process one transaction at a time. Sharding allows multiple -transactions to happen in parallel, greatly increasing the per-second +can only _fully_ process one transaction at a time. Sharding allows processing of multiple +transactions simultaneously, greatly increasing the per-second transaction capacity of Ethereum. -Each shard uses proof-of-stake and shares its validators (stakers) with the other -shards as the beacon chain rotates validators pseudo-randomly across shards. -Shards will likely be the basis of very interesting layer-2 transaction -processing schemes, however, we won't get into that here. +Each shard uses a proof-of-stake consensus mechanism and shares its validators (stakers) with other +shards. The beacon chain rotates validators pseudo-randomly between different shards. +Shards will likely be the basis of layer-2 transaction +processing schemes, however, that is not in scope of this discussion. ## The Proof-of-Work Chain -The proof-of-work chain will hold a contract that allows accounts to deposit 32 -ETH, a BLS public key and some [other -parameters](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md#pow-chain-changes) -to allow them to become Beacon Chain validators. Each Beacon Chain will -reference a PoW block hash allowing PoW clients to use the Beacon Chain as a +The proof-of-work (PoW) chain will host a smart contract that enables accounts to deposit 32 +ETH, a BLS public key, and some [other +parameters](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md#pow-chain-changes), +allowing them to become beacon chain validators. Each beacon chain will +reference a PoW block hash allowing PoW clients to use the beacon chain as a source of [Casper FFG finality](https://arxiv.org/abs/1710.09437), if desired. -It is a requirement that ETH can move freely between shard chains and between -Eth 2.0 and present-Ethereum. The exact mechanics of these transfers are still -a topic of research and their details are yet to be confirmed. +It is a requirement that ETH can move freely between shard chains, as well as between +Eth 2.0 and present-Ethereum blockchains. The exact mechanics of these transfers remain +an active topic of research and their details are yet to be confirmed. ## Ethereum 2.0 Progress -Ethereum 2.0 is not fully specified and there's no working implementation. Some -teams have demos available which indicate progress, but not a complete product. +Ethereum 2.0 is not fully specified and a working implementation does not yet exist. Some +teams have demos available which indicate progress, but do not constitute a complete product. We look forward to providing user functionality once we are ready to provide a minimum-viable user experience. -The work-in-progress specification lives +The work-in-progress Eth 2.0 specification lives [here](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md) in the [ethereum/eth2.0-specs](https://github.com/ethereum/eth2.0-specs) repository. The spec is still in a draft phase, however there are several teams -already implementing it whilst the Ethereum Foundation research team fill in -the gaps. There is active discussion about the spec in the +basing their Eth 2.0 implementations upon it while the Ethereum Foundation research +team continue to fill in the gaps. There is active discussion about the specification in the [ethereum/sharding](https://gitter.im/ethereum/sharding) gitter channel. A proof-of-concept implementation in Python is available at [ethereum/beacon_chain](https://github.com/ethereum/beacon_chain). -Presently, the spec almost exclusively defines the Beacon Chain as it -is the focus of present development efforts. Progress on shard chain +Presently, the specification focuses almost exclusively on the beacon chain, +as it is the focus of current development efforts. Progress on shard chain specification will soon follow. From 41e7199cbc1432f2d6bb30840e47e8214162b950 Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Tue, 9 Oct 2018 18:19:36 +1100 Subject: [PATCH 12/21] Fixed backslashes to forward slashes and clarified PoW chain is present-Ethereum --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9d9dd536e..c58312b38 100644 --- a/README.md +++ b/README.md @@ -160,12 +160,12 @@ always respect the limits of other people. Here we provide an overview of the directory structure: -- `\beacon_chain`: contains logic derived directly from the specification. +- `/beacon_chain`: contains logic derived directly from the specification. E.g., shuffling algorithms, state transition logic and structs, block validation, BLS crypto, etc. -- `\lighthouse`: contains logic specific to this client implementation. E.g., +- `/lighthouse`: contains logic specific to this client implementation. E.g., CLI parsing, RPC end-points, databases, etc. -- `\network-libp2p`: contains a proof-of-concept libp2p implementation. This component will be +- `/network-libp2p`: contains a proof-of-concept libp2p implementation. This component will be replaced once research around p2p has been finalized. ## Contact @@ -215,7 +215,7 @@ processing schemes, however, that is not in scope of this discussion. ## The Proof-of-Work Chain -The proof-of-work (PoW) chain will host a smart contract that enables accounts to deposit 32 +The present-Ethereum proof-of-work (PoW) chain will host a smart contract that enables accounts to deposit 32 ETH, a BLS public key, and some [other parameters](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md#pow-chain-changes), allowing them to become beacon chain validators. Each beacon chain will From d55448946f5ca91a54db9d68996baab91f9bde7a Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Tue, 9 Oct 2018 18:21:09 +1100 Subject: [PATCH 13/21] Removed the network-libp2p directory from the directory structure part of README. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index c58312b38..48317f162 100644 --- a/README.md +++ b/README.md @@ -165,8 +165,6 @@ Here we provide an overview of the directory structure: validation, BLS crypto, etc. - `/lighthouse`: contains logic specific to this client implementation. E.g., CLI parsing, RPC end-points, databases, etc. -- `/network-libp2p`: contains a proof-of-concept libp2p implementation. This component will be - replaced once research around p2p has been finalized. ## Contact From 9cefeadef1bd6e1521445c33d5e3357ccfc593da Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Wed, 10 Oct 2018 12:42:11 +1100 Subject: [PATCH 14/21] File formatting change, fixing long lines and adding minor adjustments. --- README.md | 140 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 48317f162..741700576 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![Build Status](https://travis-ci.org/sigp/lighthouse.svg?branch=master)](https://travis-ci.org/sigp/lighthouse) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sigp/lighthouse?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -A work-in-progress, open-source implementation of the Ethereum 2.0 Beacon Chain, maintained -by Sigma Prime. +A work-in-progress, open-source implementation of the Ethereum 2.0 Beacon +Chain, maintained by Sigma Prime. ## Introduction @@ -19,24 +19,24 @@ If you'd like some background on Sigma Prime, please see the [Lighthouse Update ## Lighthouse Client -Lighthouse is an open-source Ethereum 2.0 client that is currently under development. -Designed as an Ethereum 2.0-only client, Lighthouse will not re-implement the existing -proof-of-work protocol. Maintaining a forward-focus on Ethereum 2.0 ensures -that Lighthouse avoids reproducing the high-quality work already undertaken -by existing projects. As such, Lighthouse will -connect to existing clients, such as +Lighthouse is an open-source Ethereum 2.0 client that is currently under +development. Designed as an Ethereum 2.0-only client, Lighthouse will not +re-implement the existing proof-of-work protocol. Maintaining a forward-focus +on Ethereum 2.0 ensures that Lighthouse avoids reproducing the high-quality +work already undertaken by existing projects. As such, Lighthouse will connect +to existing clients, such as [Geth](https://github.com/ethereum/go-ethereum) or [Parity-Ethereum](https://github.com/paritytech/parity-ethereum), via RPC to enable present-Ethereum functionality. ### Goals -The purpose of this project is to further research and development towards a secure, -efficient, and decentralized Ethereum protocol, facilitated by a new open-source -Ethereum 2.0 client. +The purpose of this project is to further research and development towards a +secure, efficient, and decentralized Ethereum protocol, facilitated by a new +open-source Ethereum 2.0 client. -In addition to implementing a new client, the project seeks to maintain and improve -the Ethereum protocol wherever possible. +In addition to implementing a new client, the project seeks to maintain and +improve the Ethereum protocol wherever possible. ### Components @@ -45,30 +45,32 @@ by the team: - **BLS cryptography**: Lighthouse presently use the [Apache Milagro](https://milagro.apache.org/) cryptography library to create and -verify BLS aggregate signatures. BLS signatures are core to Eth 2.0 as they -allow the signatures of many validators to be compressed into a constant 96 -bytes and efficiently verified. The Lighthouse project is presently maintaining its own [BLS -aggregates library](https://github.com/sigp/signature-schemes), gratefully -forked from [@lovesh](https://github.com/lovesh). + verify BLS aggregate signatures. BLS signatures are core to Eth 2.0 as they + allow the signatures of many validators to be compressed into a constant 96 + bytes and efficiently verified. The Lighthouse project is presently + maintaining its own [BLS aggregates + library](https://github.com/sigp/signature-schemes), gratefully forked from + [@lovesh](https://github.com/lovesh). - **DoS-resistant block pre-processing**: Processing blocks in proof-of-stake is more resource intensive than proof-of-work. As such, clients need to -ensure that bad blocks can be rejected as efficiently as possible. At present, -blocks having 10 million ETH staked can be processed in 0.006 seconds, and -invalid blocks are rejected even more quickly. See -[issue #103](https://github.com/ethereum/beacon_chain/issues/103) on -[ethereum/beacon_chain](https://github.com/ethereum/beacon_chain). + ensure that bad blocks can be rejected as efficiently as possible. At + present, blocks having 10 million ETH staked can be processed in 0.006 + seconds, and invalid blocks are rejected even more quickly. See [issue + #103](https://github.com/ethereum/beacon_chain/issues/103) on + [ethereum/beacon_chain](https://github.com/ethereum/beacon_chain). . - **P2P networking**: Eth 2.0 will likely use the [libp2p framework](https://libp2p.io/). Lighthouse aims to work alongside [Parity](https://www.parity.io/) to ensure [libp2p-rust](https://github.com/libp2p/rust-libp2p) is fit-for-purpose. - **Validator duties** : The project involves development of "validator - services" for users who wish to stake ETH. To fulfill their duties, validators -require a consistent view of the chain and the ability to vote upon blocks from both shard -and beacon chains. -- **New serialization formats**: Lighthouse is working alongside researchers from the Ethereum Foundation - to develop *simpleserialize*, a purpose-built serialization format for sending -information across a network. Check out the [SSZ + services" for users who wish to stake ETH. To fulfill their duties, + validators require a consistent view of the chain and the ability to vote + upon blocks from both shard and beacon chains. +- **New serialization formats**: Lighthouse is working alongside researchers + from the Ethereum Foundation to develop *simpleserialize* (SSZ), a + purpose-built serialization format for sending information across a network. + Check out the [SSZ implementation](https://github.com/sigp/lighthouse/tree/master/beacon_chain/utils/ssz) and this [research](https://github.com/sigp/serialization_sandbox/blob/report/report/serialization_report.md) @@ -79,8 +81,8 @@ select a canonical chain in the case of a fork. - **Efficient state transition logic**: State transition logic governs updates to the validator set as validators log in/out, penalizes/rewards validators, rotates validators across shards, and implements other core tasks. -- **Fuzzing and testing environments**: Implementation of lab -environments with continuous integration (CI) workflows, providing automated security analysis. +- **Fuzzing and testing environments**: Implementation of lab environments with + continuous integration (CI) workflows, providing automated security analysis. In addition to these components we are also working on database schemas, RPC frameworks, specification development, database optimizations (e.g., @@ -91,9 +93,9 @@ bloom-filters), and tons of other interesting stuff (at least we think so). **Lighthouse welcomes contributors with open-arms.** Layer-1 infrastructure is a critical component for the ecosystem and relies -heavily on contributions from the community. Building Ethereum 2.0 is a huge task and we -refuse to conduct an inappropriate ICO or charge licensing fees. Instead, we -fund development through grants and support from Sigma Prime. +heavily on contributions from the community. Building Ethereum 2.0 is a huge +task and we refuse to conduct an inappropriate ICO or charge licensing fees. +Instead, we fund development through grants and support from Sigma Prime. If you would like to learn more about Ethereum 2.0 and/or [Rust](https://www.rust-lang.org/), we are more than happy to on-board you @@ -117,9 +119,9 @@ your support! **NOTE: The cryptography libraries used in this implementation are experimental. As such all cryptography is assumed to be insecure.** -This code-base is still very much under-development and does not provide any user-facing -functionality. For developers and researchers, there are several tests and benchmarks -which may be of interest. +This code-base is still very much under-development and does not provide any +user-facing functionality. For developers and researchers, there are several +tests and benchmarks which may be of interest. To run tests, use: @@ -142,16 +144,18 @@ Lighthouse aims to produce many small easily-tested components, each separated into individual crates wherever possible. Generally, tests can be kept in the same file, as is typical in Rust. -Integration tests should be placed in the `tests` directory in the crate's root. -Particularity large (line-count) tests should be placed into a separate file. +Integration tests should be placed in the `tests` directory in the crate's +root. Particularity large (line-count) tests should be placed into a separate +file. -A function is not considered complete until a test exists for it. We produce tests to protect -against regression (accidentally breaking things) and to provide examples that -help readers of the code base understand how functions should (or should not) be used. +A function is not considered complete until a test exists for it. We produce +tests to protect against regression (accidentally breaking things) and to +provide examples that help readers of the code base understand how functions +should (or should not) be used. -Each pull request is to be reviewed by at least one "core developer" (i.e., someone with -write-access to the repository). This helps to ensure bugs are detected, consistency is maintained, -and responsibility of errors is dispersed. +Each pull request is to be reviewed by at least one "core developer" (i.e., +someone with write-access to the repository). This helps to ensure bugs are +detected, consistency is maintained, and responsibility of errors is dispersed. Discussion must be respectful and intellectual. Have fun and make jokes, but always respect the limits of other people. @@ -174,19 +178,20 @@ Ping @paulhauner or @AgeManning to get the quickest response. # What is Ethereum 2.0 -Ethereum 2.0 refers to a new blockchain system currently under development -by the Ethereum Foundation and the Ethereum community. The Ethereum 2.0 blockchain -consists of 1,025 proof-of-stake blockchains. This includes the "beacon chain" and 1,024 -"shard chains". +Ethereum 2.0 refers to a new blockchain system currently under development by +the Ethereum Foundation and the Ethereum community. The Ethereum 2.0 blockchain +consists of 1,025 proof-of-stake blockchains. This includes the "beacon chain" +and 1,024 "shard chains". ## Beacon Chain -The concept of a beacon chain differs from existing blockchains, such as Bitcoin and -Ethereum, in that it doesn't process transactions per se. Instead, it -maintains a set of bonded (staked) validators and coordinates these to provide -services to a static set of *sub-blockchains* (i.e. shards). Each of these shard blockchains -processes normal transactions (e.g. "Transfer 5 ETH from A to B") in parallel whilst deferring -consensus mechanisms to the beacon chain. +The concept of a beacon chain differs from existing blockchains, such as +Bitcoin and Ethereum, in that it doesn't process transactions per se. Instead, +it maintains a set of bonded (staked) validators and coordinates these to +provide services to a static set of *sub-blockchains* (i.e. shards). Each of +these shard blockchains processes normal transactions (e.g. "Transfer 5 ETH +from A to B") in parallel whilst deferring consensus mechanisms to the beacon +chain. Major services provided by the beacon chain to its shards include the following: @@ -202,19 +207,20 @@ Major services provided by the beacon chain to its shards include the following: Shards are analogous to CPU cores - they're a resource where transactions can execute in series (one-after-another). Presently, Ethereum is single-core and -can only _fully_ process one transaction at a time. Sharding allows processing of multiple -transactions simultaneously, greatly increasing the per-second +can only _fully_ process one transaction at a time. Sharding allows processing +of multiple transactions simultaneously, greatly increasing the per-second transaction capacity of Ethereum. -Each shard uses a proof-of-stake consensus mechanism and shares its validators (stakers) with other -shards. The beacon chain rotates validators pseudo-randomly between different shards. -Shards will likely be the basis of layer-2 transaction -processing schemes, however, that is not in scope of this discussion. +Each shard uses a proof-of-stake consensus mechanism and shares its validators +(stakers) with other shards. The beacon chain rotates validators +pseudo-randomly between different shards. Shards will likely be the basis of +layer-2 transaction processing schemes, however, that is not in scope of this +discussion. ## The Proof-of-Work Chain -The present-Ethereum proof-of-work (PoW) chain will host a smart contract that enables accounts to deposit 32 -ETH, a BLS public key, and some [other +The present-Ethereum proof-of-work (PoW) chain will host a smart contract that +enables accounts to deposit 32 ETH, a BLS public key, and some [other parameters](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md#pow-chain-changes), allowing them to become beacon chain validators. Each beacon chain will reference a PoW block hash allowing PoW clients to use the beacon chain as a @@ -226,10 +232,10 @@ an active topic of research and their details are yet to be confirmed. ## Ethereum 2.0 Progress -Ethereum 2.0 is not fully specified and a working implementation does not yet exist. Some -teams have demos available which indicate progress, but do not constitute a complete product. -We look forward to providing user functionality once we are ready to provide a -minimum-viable user experience. +Ethereum 2.0 is not fully specified and a working implementation does not yet +exist. Some teams have demos available which indicate progress, but do not +constitute a complete product. We look forward to providing user functionality +once we are ready to provide a minimum-viable user experience. The work-in-progress Eth 2.0 specification lives [here](https://github.com/ethereum/eth2.0-specs/blob/master/specs/casper_sharding_v2.1.md) From 6417ecd464914a28200bb8d94131ec81ea789d12 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 10 Oct 2018 14:04:42 +1100 Subject: [PATCH 15/21] Correct comments for rust docs --- .../transition/src/delegation/validator.rs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index b745fa3f4..15dca2278 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -31,7 +31,7 @@ impl<'a,T> Iterator for Split<'a, T> { } -/// splits a slice into chunks of size n. All postive n values are applicable, +/// Splits a slice into chunks of size n. All postive n values are applicable, /// hence the honey_badger prefix. /// Returns an iterator over the original list. trait SplitExt { @@ -51,9 +51,8 @@ impl SplitExt for [T] { } -/* Produce a vector of validators indicies where those validators start and end - * dynasties are within the supplied `dynasty`. -*/ +/// 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: &[ValidatorRecord]) @@ -73,12 +72,11 @@ fn active_validator_indicies( .collect() } -/* - * Delegates active validators into slots for a given cycle, given a random seed. - * Returns a vector or ShardAndComitte vectors representing the shards and committiees for - * each slot. - * References get_new_shuffling (ethereum 2.1 specification) - */ + +/// Delegates active validators into slots for a given cycle, given a random seed. +/// Returns a vector or ShardAndComitte vectors representing the shards and committiees for +/// each slot. +/// References get_new_shuffling (ethereum 2.1 specification) pub fn delegate_validators( seed: &[u8], validators: &[ValidatorRecord], @@ -107,9 +105,7 @@ pub fn delegate_validators( min_committee_size) } -/* - * Given the validator list, delegates the validators into slots and comittees for a given cycle. - */ +/// Given the validator list, delegates the validators into slots and comittees for a given cycle. fn generate_cycle( validator_indices: &[usize], shard_indices: &[usize], From 9717698f7b894b08fba5ce788022017773d2d086 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 10 Oct 2018 16:09:00 +1100 Subject: [PATCH 16/21] Break split function into its own crate. - Added tests - Remove it from the delegation dir - Added it as a crate in utils --- Cargo.toml | 1 + beacon_chain/transition/Cargo.toml | 1 + beacon_chain/transition/src/delegation/mod.rs | 1 + .../transition/src/delegation/validator.rs | 47 +--------- beacon_chain/transition/src/lib.rs | 1 + .../utils/honey-badger-split/Cargo.toml | 6 ++ .../utils/honey-badger-split/src/lib.rs | 85 +++++++++++++++++++ 7 files changed, 96 insertions(+), 46 deletions(-) create mode 100644 beacon_chain/utils/honey-badger-split/Cargo.toml create mode 100644 beacon_chain/utils/honey-badger-split/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 53f3fd00d..58e91040c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ members = [ "beacon_chain/utils/bls", "beacon_chain/utils/boolean-bitfield", "beacon_chain/utils/hashing", + "beacon_chain/utils/honey-badger-split", "beacon_chain/utils/shuffling", "beacon_chain/utils/ssz", "beacon_chain/utils/ssz_helpers", diff --git a/beacon_chain/transition/Cargo.toml b/beacon_chain/transition/Cargo.toml index abf1fe6dc..c17d6994f 100644 --- a/beacon_chain/transition/Cargo.toml +++ b/beacon_chain/transition/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" authors = ["Age Manning "] [dependencies] +honey-badger-split = { path = "../utils/honey-badger-split" } types = { path = "../types" } shuffling = { path = "../utils/shuffling" } diff --git a/beacon_chain/transition/src/delegation/mod.rs b/beacon_chain/transition/src/delegation/mod.rs index 265b3e9b6..66f3304f3 100644 --- a/beacon_chain/transition/src/delegation/mod.rs +++ b/beacon_chain/transition/src/delegation/mod.rs @@ -1,3 +1,4 @@ +use super::honey_badger_split; use super::types; use super::TransitionError; use super::shuffling::shuffle; diff --git a/beacon_chain/transition/src/delegation/validator.rs b/beacon_chain/transition/src/delegation/validator.rs index 15dca2278..4c33d0081 100644 --- a/beacon_chain/transition/src/delegation/validator.rs +++ b/beacon_chain/transition/src/delegation/validator.rs @@ -1,3 +1,4 @@ +use super::honey_badger_split::SplitExt; use super::types::{ShardAndCommittee, ValidatorRecord, ChainConfig}; use super::TransitionError; use super::shuffle; @@ -5,52 +6,6 @@ use std::cmp::min; type DelegatedCycle = Vec>; -/// Iterator for the honey_badger_split function -struct Split<'a, T: 'a> { - n: usize, - current_pos: usize, - list: &'a [T], - list_length: usize -} - -impl<'a,T> Iterator for Split<'a, T> { - type Item = &'a [T]; - - fn next(&mut self) -> Option { - self.current_pos +=1; - if self.current_pos <= self.n { - match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) { - Some(v) => Some(v), - None => unreachable!() - } - } - else { - None - } - } -} - - -/// Splits a slice into chunks of size n. All postive n values are applicable, -/// hence the honey_badger prefix. -/// Returns an iterator over the original list. -trait SplitExt { - fn honey_badger_split(&self, n: usize) -> Split; -} - -impl SplitExt for [T] { - - fn honey_badger_split(&self, n: usize) -> Split { - Split { - n, - current_pos: 0, - list: &self, - list_length: self.len(), - } - } -} - - /// Produce a vector of validators indicies where those validators start and end /// dynasties are within the supplied `dynasty`. fn active_validator_indicies( diff --git a/beacon_chain/transition/src/lib.rs b/beacon_chain/transition/src/lib.rs index a86777e9b..ccac52529 100644 --- a/beacon_chain/transition/src/lib.rs +++ b/beacon_chain/transition/src/lib.rs @@ -1,3 +1,4 @@ +extern crate honey_badger_split; extern crate types; extern crate shuffling; diff --git a/beacon_chain/utils/honey-badger-split/Cargo.toml b/beacon_chain/utils/honey-badger-split/Cargo.toml new file mode 100644 index 000000000..e9721efd4 --- /dev/null +++ b/beacon_chain/utils/honey-badger-split/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "honey-badger-split" +version = "0.1.0" +authors = ["Paul Hauner "] + +[dependencies] diff --git a/beacon_chain/utils/honey-badger-split/src/lib.rs b/beacon_chain/utils/honey-badger-split/src/lib.rs new file mode 100644 index 000000000..890391036 --- /dev/null +++ b/beacon_chain/utils/honey-badger-split/src/lib.rs @@ -0,0 +1,85 @@ +/// A function for splitting a list into N pieces. +/// +/// We have titled it the "honey badger split" because of its robustness. It don't care. + + +/// Iterator for the honey_badger_split function +pub struct Split<'a, T: 'a> { + n: usize, + current_pos: usize, + list: &'a [T], + list_length: usize +} + +impl<'a,T> Iterator for Split<'a, T> { + type Item = &'a [T]; + + fn next(&mut self) -> Option { + self.current_pos +=1; + if self.current_pos <= self.n { + match self.list.get(self.list_length*(self.current_pos-1)/self.n..self.list_length*self.current_pos/self.n) { + Some(v) => Some(v), + None => unreachable!() + } + } + else { + None + } + } +} + +/// Splits a slice into chunks of size n. All postive n values are applicable, +/// hence the honey_badger prefix. +/// +/// Returns an iterator over the original list. +pub trait SplitExt { + fn honey_badger_split(&self, n: usize) -> Split; +} + +impl SplitExt for [T] { + + fn honey_badger_split(&self, n: usize) -> Split { + Split { + n, + current_pos: 0, + list: &self, + list_length: self.len(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_honey_badger_split() { + /* + * These test cases are generated from the eth2.0 spec `split()` + * function at commit cbd254a. + */ + let input: Vec = vec![0, 1, 2, 3]; + let output: Vec<&[usize]> = input.honey_badger_split(2).collect(); + assert_eq!(output, vec![&[0, 1], &[2, 3]]); + + let input: Vec = vec![0, 1, 2, 3]; + let output: Vec<&[usize]> = input.honey_badger_split(6).collect(); + let expected: Vec<&[usize]> = vec![&[], &[0], &[1], &[], &[2], &[3]]; + assert_eq!(output, expected); + + let input: Vec = vec![0, 1, 2, 3]; + let output: Vec<&[usize]> = input.honey_badger_split(10).collect(); + let expected: Vec<&[usize]> = vec![&[], &[], &[0], &[], &[1], &[], &[], &[2], &[], &[3]]; + assert_eq!(output, expected); + + let input: Vec = vec![0]; + let output: Vec<&[usize]> = input.honey_badger_split(5).collect(); + let expected: Vec<&[usize]> = vec![&[], &[], &[], &[], &[0]]; + assert_eq!(output, expected); + + let input: Vec = vec![0, 1, 2]; + let output: Vec<&[usize]> = input.honey_badger_split(2).collect(); + let expected: Vec<&[usize]> = vec![&[0], &[1, 2]]; + assert_eq!(output, expected); + } +} From 90010ced55b95fcdc9290945b383dd2519fff036 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 13 Oct 2018 09:39:10 +1100 Subject: [PATCH 17/21] Fix big in attestation validation There was no check that the attestation is within an appropriate distance from its parent block. --- beacon_chain/validation/src/attestation_validation.rs | 7 ++++--- .../validation/tests/attestation_validation/tests.rs | 11 ++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/beacon_chain/validation/src/attestation_validation.rs b/beacon_chain/validation/src/attestation_validation.rs index bb458ebc7..057703013 100644 --- a/beacon_chain/validation/src/attestation_validation.rs +++ b/beacon_chain/validation/src/attestation_validation.rs @@ -29,6 +29,7 @@ use super::signature_verification::{ #[derive(Debug,PartialEq)] pub enum AttestationValidationError { ParentSlotTooHigh, + ParentSlotTooLow, BlockSlotTooHigh, BlockSlotTooLow, JustifiedSlotIncorrect, @@ -94,11 +95,11 @@ impl AttestationValidationContext /* * The slot of this attestation must not be more than cycle_length + 1 distance - * from the block that contained it. + * from the parent_slot of block that contained it. */ - if a.slot < self.block_slot + if a.slot < self.parent_block_slot .saturating_sub(u64::from(self.cycle_length).saturating_add(1)) { - return Err(AttestationValidationError::BlockSlotTooLow); + return Err(AttestationValidationError::ParentSlotTooLow); } /* diff --git a/beacon_chain/validation/tests/attestation_validation/tests.rs b/beacon_chain/validation/tests/attestation_validation/tests.rs index f09da3313..013750af3 100644 --- a/beacon_chain/validation/tests/attestation_validation/tests.rs +++ b/beacon_chain/validation/tests/attestation_validation/tests.rs @@ -42,6 +42,15 @@ fn test_attestation_validation_invalid_parent_slot_too_high() { assert_eq!(result, Err(AttestationValidationError::ParentSlotTooHigh)); } +#[test] +fn test_attestation_validation_invalid_parent_slot_too_low() { + let mut rig = generic_rig(); + + rig.attestation.slot = rig.context.parent_block_slot - u64::from(rig.context.cycle_length) - 2; + let result = rig.context.validate_attestation(&rig.attestation); + assert_eq!(result, Err(AttestationValidationError::ParentSlotTooLow)); +} + #[test] fn test_attestation_validation_invalid_block_slot_too_high() { let mut rig = generic_rig(); @@ -56,7 +65,7 @@ fn test_attestation_validation_invalid_block_slot_too_high() { fn test_attestation_validation_invalid_block_slot_too_low() { let mut rig = generic_rig(); - rig.attestation.slot = rig.context.block_slot - u64::from(rig.context.cycle_length) - 2; + rig.context.block_slot = rig.context.block_slot + u64::from(rig.context.cycle_length); let result = rig.context.validate_attestation(&rig.attestation); assert_eq!(result, Err(AttestationValidationError::BlockSlotTooLow)); } From 14d9df3321ee2a6ed5b91af425f9c165b63fdf45 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 14 Oct 2018 14:17:26 +1100 Subject: [PATCH 18/21] Add CONTRIBUTING.md --- CONTRIBUTING.md | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..b1142c72e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,118 @@ +# Contributors Guide + +Lighthouse is an open-source Ethereum 2.0 client. We we're community driven and +welcome all contribution. We aim to provide a constructive, respectful and fun +environment for collaboration. + +We are active contributors to the [Ethereum 2.0 specification](https://github.com/ethereum/eth2.0-specs) and attend all [Eth +2.0 implementers calls](https://github.com/ethereum/eth2.0-pm). + +This guide is geared towards beginners. If you're an open-source veteran feel +free to just skim this document and get straight into crushing issues. + +## Why Contribute + +There are many reasons you might contribute to Lighthouse. For example, you may +wish to: + +- contribute to the Ethereum ecosystem. +- establish yourself as a layer-1 Ethereum developer. +- work in the amazing Rust programming language. +- learn how to participate in open-source projects. +- expand your software development skills. +- flex your skills in a public forum to expand your career + opportunities (or simply for the fun of it). +- grow your network by working with core Ethereum developers. + +## How to Contribute + +Regardless of the reason, the process to begin contributing is very much the +same. We operate like a typical open-source project operating on GitHub: the +repository [Issues](https://github.com/sigp/lighthouse/issues) is where we +track what needs to be done and [Pull +Requests](https://github.com/sigp/lighthouse/pulls) is where code gets +reviewed. We use [gitter](https://gitter.im/sigp/lighthouse) to chat +informally. + +### General Work-Flow + +We recommend the following work-flow for contributors: + +1. **Find an issue** to work on, either because it's interesting or suitable to + your skill-set. Use comments to communicate your intentions and ask +questions. +2. **Work in a feature branch** of your personal fork + (github.com/YOUR_NAME/lighthouse) of the main repository + (github.com/sigp/lighthouse). +3. Once you feel you have addressed the issue, **create a pull-request** to merge + your changes in to the main repository. +4. Wait for the repository maintainers to **review your changes** to ensure the + issue is addressed satisfactorily. Optionally, mention your PR on +[gitter](https://gitter.im/sigp/lighthouse). +5. If the issue is addressed the repository maintainers will **merge your + pull-request** and you'll be an official contributor! + +Generally, you find an issue you'd like to work on and announce your intentions +to start work in a comment on the issue. Then, do your work on a separate +branch (a "feature branch") in your own fork of the main repository. Once +you're happy and you think the issue has been addressed, create a pull request +into the main repository. + +### First-time Set-up + +First time contributors can get their git environment up and running with these +steps: + +1. [Create a + fork](https://help.github.com/articles/fork-a-repo/#fork-an-example-repository) +and [clone +it](https://help.github.com/articles/fork-a-repo/#step-2-create-a-local-clone-of-your-fork) +to your local machine. +2. [Add an _"upstream"_ + branch](https://help.github.com/articles/fork-a-repo/#step-3-configure-git-to-sync-your-fork-with-the-original-spoon-knife-repository) +that tracks github.com/sigp/lighthouse using `$ git remote add upstream +https://github.com/sigp/lighthouse.git` (pro-tip: [use SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) instead of HTTPS). +3. Create a new feature branch with `$ git checkout -b your_feature_name`. The + name of your branch isn't critical but it should be short and instructive. +E.g., if you're fixing a bug with serialization, you could name your branch +`fix_serialization_bug`. +4. Commit your changes and push them to your fork with `$ git push origin + your_feature_name`. +5. Go to your fork on github.com and use the web interface to create a pull + request into the sigp/lighthouse repo. + +From there, the repository maintainers will review the PR and either accept it +or provide some constructive feedback. + +There's great +[guide](https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/) +by Rob Allen that provides much more detail on each of these steps, if you're +having trouble. As always, jump on [gitter](https://gitter.im/sigp/lighthouse) +if you get stuck. + + +## FAQs + +### I don't think I have anything to add + +There's lots to be done and there's all sorts of tasks. You can do anything +from correcting typos through to writing core consensus code. If you reach out, +we'll include you. + +### I'm not sure my Rust is good enough + +We're open to developers of all levels. If you create a PR and your code +doesn't meet our standards, we'll help you fix it and we'll share the reasoning +with you. Contributing to open-source is a great way to learn. + +### I'm not sure I know enough about Ethereum 2.0 + +No problems, there's plenty of tasks that don't require extensive Ethereum +knowledge. You can learn about Ethereum as you go. + +### I'm afraid of making a mistake and looking silly + +Don't be. We're all about personal development and constructive feedback. If you +make a mistake and learn from it, everyone wins. + +hi From 32e8af97de0f8a742de3d48319cd0341c2c14609 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 14 Oct 2018 14:29:18 +1100 Subject: [PATCH 19/21] Remove image, add FAQ to contributing.md --- CONTRIBUTING.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b1142c72e..e5b34f083 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -115,4 +115,7 @@ knowledge. You can learn about Ethereum as you go. Don't be. We're all about personal development and constructive feedback. If you make a mistake and learn from it, everyone wins. -hi +### I don't like the way you do things + +Please, make an issue and explain why. We're open to constructive criticism and +will happily change our ways. From c327ef970b46ff76cb006b498c2fb0e7092e4a4d Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 14 Oct 2018 14:51:59 +1100 Subject: [PATCH 20/21] Add PR and issue templates --- .github/ISSUE_TEMPLATE.md | 16 ++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 12 ++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..7ecb9e5b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,16 @@ +## Description + +Please provide a brief description of the issue. + +## Present Behaviour + +Describe the present behaviour of the application, with regards to this +issue. + +## Expected Behaviour + +How _should_ the application behave? + +## Steps to resolve + +Please describe the steps required to resolve this issue, if known. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..01ca90a79 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +## Issue Addressed + +Which issue # does this PR address? + +## Proposed Changes + +Please list or describe the changes introduced by this PR. + +## Additional Info + +Please provide any additional information. For example, future considerations +or information useful for reviewers. From dbff403171138178390fad94c706b2b55d889c5e Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 15 Oct 2018 09:58:45 +1100 Subject: [PATCH 21/21] Remove gitmodules. Previously parity-ethereum was a submodule but that is no longer the case. I can't see any reason we'll add a gitmodule in the near future. --- .gitmodules | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29bb..000000000