From 89bea5b5e8f78ef7274fcb40fce07544b67fb7be Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 12 Dec 2018 18:25:21 +1100 Subject: [PATCH 01/14] Update `BeaconState` rename `ShardCommittee` Both structs are now consistent with the spec. Addresses #100 --- beacon_chain/types/src/beacon_state.rs | 25 +++++++++++++------ beacon_chain/types/src/lib.rs | 4 +-- ...rd_and_committee.rs => shard_committee.rs} | 4 +-- 3 files changed, 22 insertions(+), 11 deletions(-) rename beacon_chain/types/src/{shard_and_committee.rs => shard_committee.rs} (90%) diff --git a/beacon_chain/types/src/beacon_state.rs b/beacon_chain/types/src/beacon_state.rs index 2f5581d57f..03f2c93aaa 100644 --- a/beacon_chain/types/src/beacon_state.rs +++ b/beacon_chain/types/src/beacon_state.rs @@ -2,33 +2,44 @@ use super::candidate_pow_receipt_root_record::CandidatePoWReceiptRootRecord; use super::crosslink_record::CrosslinkRecord; use super::fork_data::ForkData; use super::pending_attestation_record::PendingAttestationRecord; -use super::shard_and_committee::ShardAndCommittee; +use super::shard_committee::ShardCommittee; use super::shard_reassignment_record::ShardReassignmentRecord; use super::validator_record::ValidatorRecord; use super::Hash256; #[derive(Debug, PartialEq)] pub struct BeaconState { + // Misc + pub slot: u64, + pub genesis_time: u64, + pub fork_data: ForkData, + + // Validator registry pub validator_registry: Vec, pub validator_registry_latest_change_slot: u64, pub validator_registry_exit_count: u64, pub validator_registry_delta_chain_tip: Hash256, + + // Randomness and committees pub randao_mix: Hash256, pub next_seed: Hash256, - pub shard_and_committee_for_slots: Vec>, + pub shard_committees_at_slots: Vec>, pub persistent_committees: Vec>, pub persistent_committee_reassignments: Vec, + + // Finality pub previous_justified_slot: u64, pub justified_slot: u64, - pub justified_slot_bitfield: u64, + pub justification_bitfield: u64, pub finalized_slot: u64, + + // Recent state pub latest_crosslinks: Vec, - pub latest_state_recalculation_slot: u64, - pub latest_block_hashes: Vec, + pub latest_block_roots: Vec, pub latest_penalized_exit_balances: Vec, pub latest_attestations: Vec, + + // PoW receipt root pub processed_pow_receipt_root: Hash256, pub candidate_pow_receipt_roots: Vec, - pub genesis_time: u64, - pub fork_data: ForkData, } diff --git a/beacon_chain/types/src/lib.rs b/beacon_chain/types/src/lib.rs index f86d5f0247..65299d5d1d 100644 --- a/beacon_chain/types/src/lib.rs +++ b/beacon_chain/types/src/lib.rs @@ -14,7 +14,7 @@ pub mod crosslink_record; pub mod crystallized_state; pub mod fork_data; pub mod pending_attestation_record; -pub mod shard_and_committee; +pub mod shard_committee; pub mod shard_reassignment_record; pub mod special_record; pub mod validator_record; @@ -33,7 +33,7 @@ pub use crosslink_record::CrosslinkRecord; pub use crystallized_state::CrystallizedState; pub use fork_data::ForkData; pub use pending_attestation_record::PendingAttestationRecord; -pub use shard_and_committee::ShardAndCommittee; +pub use shard_committee::ShardCommittee; pub use special_record::{SpecialRecord, SpecialRecordKind}; pub use validator_record::{ValidatorRecord, ValidatorStatus}; pub use validator_registration::ValidatorRegistration; diff --git a/beacon_chain/types/src/shard_and_committee.rs b/beacon_chain/types/src/shard_committee.rs similarity index 90% rename from beacon_chain/types/src/shard_and_committee.rs rename to beacon_chain/types/src/shard_committee.rs index 44c2e57ffb..2dc0f6a757 100644 --- a/beacon_chain/types/src/shard_and_committee.rs +++ b/beacon_chain/types/src/shard_committee.rs @@ -1,10 +1,10 @@ #[derive(Clone, Debug, PartialEq)] -pub struct ShardAndCommittee { +pub struct ShardCommittee { pub shard: u16, pub committee: Vec, } -impl ShardAndCommittee { +impl ShardCommittee { /// Returns a new instance where the `shard_id` is zero and the /// committee is an empty vector. pub fn zero() -> Self { From c944c435e2853a1687b5a5331ac0e9a326fdf967 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 12 Dec 2018 18:30:20 +1100 Subject: [PATCH 02/14] Update `CrosslinkRecord` to latest spec Addresses #100 --- beacon_chain/types/src/crosslink_record.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon_chain/types/src/crosslink_record.rs b/beacon_chain/types/src/crosslink_record.rs index 3f7ac2f1af..6a70daade4 100644 --- a/beacon_chain/types/src/crosslink_record.rs +++ b/beacon_chain/types/src/crosslink_record.rs @@ -3,7 +3,7 @@ use super::Hash256; #[derive(Clone, Debug, PartialEq)] pub struct CrosslinkRecord { pub slot: u64, - pub shard_block_hash: Hash256, + pub shard_block_root: Hash256, } impl CrosslinkRecord { @@ -11,7 +11,7 @@ impl CrosslinkRecord { pub fn zero() -> Self { Self { slot: 0, - shard_block_hash: Hash256::zero(), + shard_block_root: Hash256::zero(), } } } From 92786520e4a8eee3274227fb5a3ccacdc7d88827 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 12 Dec 2018 18:32:19 +1100 Subject: [PATCH 03/14] Update (hacky) validator induction and shuffling. This allows the `BeaconChain` struct to be updated but it doesn't bring these functions in line with the spec. --- .../validator_induction/src/inductor.rs | 2 +- beacon_chain/validator_shuffling/Cargo.toml | 1 + beacon_chain/validator_shuffling/src/lib.rs | 1 + .../validator_shuffling/src/shuffle.rs | 41 ++++++++++--------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index c86fce9e60..d26e71bc34 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -19,7 +19,7 @@ pub enum ValidatorInductionError { } impl ValidatorInductor { - pub fn new(current_slot: u64, shard_count: u16, validators: Vec) -> Self { + pub fn new(current_slot: u64, shard_count: u64, validators: Vec) -> Self { Self { current_slot, shard_count, diff --git a/beacon_chain/validator_shuffling/Cargo.toml b/beacon_chain/validator_shuffling/Cargo.toml index 269b5c5576..b6c35ec3f6 100644 --- a/beacon_chain/validator_shuffling/Cargo.toml +++ b/beacon_chain/validator_shuffling/Cargo.toml @@ -6,5 +6,6 @@ authors = ["Paul Hauner "] [dependencies] active-validators = { path = "../utils/active-validators" } honey-badger-split = { path = "../utils/honey-badger-split" } +spec = { path = "../spec" } types = { path = "../types" } vec_shuffle = { path = "../utils/vec_shuffle" } diff --git a/beacon_chain/validator_shuffling/src/lib.rs b/beacon_chain/validator_shuffling/src/lib.rs index fe2447fc05..61cc02bf1d 100644 --- a/beacon_chain/validator_shuffling/src/lib.rs +++ b/beacon_chain/validator_shuffling/src/lib.rs @@ -1,5 +1,6 @@ extern crate active_validators; extern crate honey_badger_split; +extern crate spec; extern crate types; extern crate vec_shuffle; diff --git a/beacon_chain/validator_shuffling/src/shuffle.rs b/beacon_chain/validator_shuffling/src/shuffle.rs index 3009f4cbd8..3b3009e5d4 100644 --- a/beacon_chain/validator_shuffling/src/shuffle.rs +++ b/beacon_chain/validator_shuffling/src/shuffle.rs @@ -2,7 +2,8 @@ use std::cmp::min; use active_validators::active_validator_indices; use honey_badger_split::SplitExt; -use types::{ChainConfig, ShardAndCommittee, ValidatorRecord}; +use spec::ChainSpec; +use types::{ShardAndCommittee, ValidatorRecord}; use vec_shuffle::{shuffle, ShuffleErr}; type DelegatedCycle = Vec>; @@ -21,21 +22,21 @@ pub fn shard_and_committees_for_cycle( seed: &[u8], validators: &[ValidatorRecord], crosslinking_shard_start: u16, - config: &ChainConfig, + spec: &ChainSpec, ) -> Result { let shuffled_validator_indices = { let mut validator_indices = active_validator_indices(validators); shuffle(seed, validator_indices)? }; - let shard_indices: Vec = (0_usize..config.shard_count as usize).into_iter().collect(); + let shard_indices: Vec = (0_usize..spec.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; + let epoch_length = spec.epoch_length as usize; + let min_committee_size = spec.target_committee_size as usize; generate_cycle( &shuffled_validator_indices, &shard_indices, crosslinking_shard_start, - cycle_length, + epoch_length, min_committee_size, ) } @@ -45,29 +46,29 @@ fn generate_cycle( validator_indices: &[usize], shard_indices: &[usize], crosslinking_shard_start: usize, - cycle_length: usize, + epoch_length: usize, min_committee_size: usize, ) -> Result { let validator_count = validator_indices.len(); let shard_count = shard_indices.len(); - if shard_count / cycle_length == 0 { + if shard_count / epoch_length == 0 { return Err(ValidatorAssignmentError::TooFewShards); } let (committees_per_slot, slots_per_committee) = { - if validator_count >= cycle_length * min_committee_size { + if validator_count >= epoch_length * min_committee_size { let committees_per_slot = min( - validator_count / cycle_length / (min_committee_size * 2) + 1, - shard_count / cycle_length, + validator_count / epoch_length / (min_committee_size * 2) + 1, + shard_count / epoch_length, ); 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) + while (validator_count * slots_per_committee < epoch_length * min_committee_size) + & (slots_per_committee < epoch_length) { slots_per_committee *= 2; } @@ -76,7 +77,7 @@ fn generate_cycle( }; let cycle = validator_indices - .honey_badger_split(cycle_length) + .honey_badger_split(epoch_length) .enumerate() .map(|(i, slot_indices)| { let shard_start = @@ -108,7 +109,7 @@ mod tests { validator_count: &usize, shard_count: &usize, crosslinking_shard_start: usize, - cycle_length: usize, + epoch_length: usize, min_committee_size: usize, ) -> ( Vec, @@ -121,7 +122,7 @@ mod tests { &validator_indices, &shard_indices, crosslinking_shard_start, - cycle_length, + epoch_length, min_committee_size, ); (validator_indices, shard_indices, result) @@ -183,13 +184,13 @@ mod tests { let validator_count: usize = 100; let shard_count: usize = 20; let crosslinking_shard_start: usize = 0; - let cycle_length: usize = 20; + let epoch_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, + epoch_length, min_committee_size, ); let cycle = result.unwrap(); @@ -242,13 +243,13 @@ mod tests { let validator_count: usize = 523; let shard_count: usize = 31; let crosslinking_shard_start: usize = 0; - let cycle_length: usize = 11; + let epoch_length: usize = 11; let min_committee_size: usize = 5; let (validators, shards, result) = generate_cycle_helper( &validator_count, &shard_count, crosslinking_shard_start, - cycle_length, + epoch_length, min_committee_size, ); let cycle = result.unwrap(); From 56dc73fbd1d2686b5282070fba54cf70de0ac041 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 12 Dec 2018 18:35:31 +1100 Subject: [PATCH 04/14] Update some shard `u16` to `u64` This is pretty hacky, is just serving my purpose for `BeaconChain`. These structs will need to be fully updated to the latest spec. --- beacon_chain/types/src/validator_record.rs | 2 +- beacon_chain/types/src/validator_registration.rs | 2 +- beacon_chain/validator_induction/src/inductor.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_chain/types/src/validator_record.rs b/beacon_chain/types/src/validator_record.rs index 3a15baeecb..692d81801a 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -14,7 +14,7 @@ pub enum ValidatorStatus { #[derive(Debug, Clone, PartialEq)] pub struct ValidatorRecord { pub pubkey: PublicKey, - pub withdrawal_shard: u16, + pub withdrawal_shard: u64, pub withdrawal_address: Address, pub randao_commitment: Hash256, pub randao_last_change: u64, diff --git a/beacon_chain/types/src/validator_registration.rs b/beacon_chain/types/src/validator_registration.rs index 139885b1cc..11f6d11c50 100644 --- a/beacon_chain/types/src/validator_registration.rs +++ b/beacon_chain/types/src/validator_registration.rs @@ -5,7 +5,7 @@ use bls::{create_proof_of_possession, Keypair, PublicKey, Signature}; #[derive(Debug, Clone, PartialEq)] pub struct ValidatorRegistration { pub pubkey: PublicKey, - pub withdrawal_shard: u16, + pub withdrawal_shard: u64, pub withdrawal_address: Address, pub randao_commitment: Hash256, pub proof_of_possession: Signature, diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index d26e71bc34..03a04e1ca4 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -7,7 +7,7 @@ pub const DEPOSIT_GWEI: u64 = 32_000_000_000; /// Inducts validators into a `CrystallizedState`. pub struct ValidatorInductor { pub current_slot: u64, - pub shard_count: u16, + pub shard_count: u64, validators: Vec, empty_validator_start: usize, } From bf49c881d55484599a68c5316308b60291586924 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 12 Dec 2018 18:36:12 +1100 Subject: [PATCH 05/14] Introduce un-tested BeaconState genesis code. --- beacon_chain/chain/Cargo.toml | 1 + beacon_chain/chain/src/genesis.rs | 72 +++++++++++++++++++++++++++---- beacon_chain/chain/src/lib.rs | 7 ++- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/beacon_chain/chain/Cargo.toml b/beacon_chain/chain/Cargo.toml index 479804f45e..973e1560a0 100644 --- a/beacon_chain/chain/Cargo.toml +++ b/beacon_chain/chain/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Paul Hauner "] bls = { path = "../utils/bls" } db = { path = "../../lighthouse/db" } naive_fork_choice = { path = "../naive_fork_choice" } +spec = { path = "../spec" } ssz = { path = "../utils/ssz" } ssz_helpers = { path = "../utils/ssz_helpers" } state-transition = { path = "../state-transition" } diff --git a/beacon_chain/chain/src/genesis.rs b/beacon_chain/chain/src/genesis.rs index d9b634062f..0444c9f294 100644 --- a/beacon_chain/chain/src/genesis.rs +++ b/beacon_chain/chain/src/genesis.rs @@ -1,5 +1,7 @@ -use super::{ActiveState, ChainConfig, CrystallizedState}; -use types::ValidatorStatus; +use spec::ChainSpec; +use types::{ + BeaconState, CrosslinkRecord, ForkData, Hash256, ValidatorRegistration, ValidatorStatus, +}; use validator_induction::ValidatorInductor; use validator_shuffling::{shard_and_committees_for_cycle, ValidatorAssignmentError}; @@ -18,15 +20,20 @@ impl From for Error { /// Initialize a new ChainHead with genesis parameters. /// /// Used when syncing a chain from scratch. -pub fn genesis_states(config: &ChainConfig) -> Result<(ActiveState, CrystallizedState), Error> { +pub fn genesis_states( + spec: &ChainSpec, + initial_validators: Vec, + genesis_time: u64, + processed_pow_receipt_root: Hash256, +) -> Result { /* * Parse the ValidatorRegistrations into ValidatorRecords and induct them. * * Ignore any records which fail proof-of-possession or are invalid. */ let validators = { - let mut inductor = ValidatorInductor::new(0, config.shard_count, vec![]); - for registration in &config.initial_validators { + let mut inductor = ValidatorInductor::new(0, spec.shard_count, vec![]); + for registration in &initial_validators { let _ = inductor.induct(®istration, ValidatorStatus::Active); } inductor.to_vec() @@ -38,16 +45,63 @@ pub fn genesis_states(config: &ChainConfig) -> Result<(ActiveState, Crystallized * Crystallizedstate stores two cycles, so we simply repeat the same assignment twice. */ let _shard_and_committee_for_slots = { - let mut a = shard_and_committees_for_cycle(&vec![0; 32], &validators, 0, &config)?; + let mut a = shard_and_committees_for_cycle(&vec![0; 32], &validators, 0, &spec)?; let mut b = a.clone(); a.append(&mut b); a }; - // TODO: implement genesis for `BeaconState` - // https://github.com/sigp/lighthouse/issues/99 + let initial_crosslink = CrosslinkRecord { + slot: spec.initial_slot_number, + shard_block_root: spec.zero_hash, + }; - Err(Error::NotImplemented) + Ok(BeaconState { + /* + * Misc + */ + slot: spec.initial_slot_number, + genesis_time, + fork_data: ForkData { + pre_fork_version: spec.initial_fork_version, + post_fork_version: spec.initial_fork_version, + fork_slot: spec.initial_slot_number, + }, + /* + * Validator registry + */ + validator_registry: validators, + validator_registry_latest_change_slot: spec.initial_slot_number, + validator_registry_exit_count: 0, + validator_registry_delta_chain_tip: spec.zero_hash, + /* + * Randomness and committees + */ + randao_mix: spec.zero_hash, + next_seed: spec.zero_hash, + shard_committees_at_slot: vec![], + persistent_committees: vec![], + persisten_committee_reassignments: vec![], + /* + * Finality + */ + previous_justified_slot: spec.initial_slot_number, + justified_slot: spec.initial_slot_number, + justified_bitfield: 0, + finalized_slot: spec.initial_slot_number, + /* + * Recent state + */ + latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize], + latest_block_roots: vec![spec.zero_hash; spec.epoch_length as usize], + latest_penalized_exit_balances: vec![], + latest_attestations: vec![], + /* + * PoW receipt root + */ + processed_pow_receipt_root, + candidate_pow_receipt_roots: vec![], + }) } #[cfg(test)] diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index 0837f3bafa..5fc9dc0773 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -1,5 +1,6 @@ extern crate db; extern crate naive_fork_choice; +extern crate spec; extern crate ssz; extern crate ssz_helpers; extern crate state_transition; @@ -37,10 +38,8 @@ pub struct BeaconChain { pub head_block_hashes: Vec, /// The index of the canonical block in `head_block_hashes`. pub canonical_head_block_hash: usize, - /// A map where the value is an active state the the key is its hash. - pub active_states: HashMap, - /// A map where the value is crystallized state the the key is its hash. - pub crystallized_states: HashMap, + /// An in-memory map of root hash to beacon state. + pub beacon_states: HashMap, /// A map of crystallized state to a proposer and attester map. pub attester_proposer_maps: HashMap, Arc)>, /// A collection of database stores used by the chain. From 6847e68c5eb1ff4bd949635c4cc963c722ec4dc5 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 12:27:45 +1100 Subject: [PATCH 06/14] Move genesis code into its own crate --- Cargo.toml | 1 + beacon_chain/chain/src/lib.rs | 1 - beacon_chain/genesis/Cargo.toml | 11 ++ .../src/beacon_state.rs} | 146 +++++++----------- beacon_chain/genesis/src/lib.rs | 7 + beacon_chain/spec/src/lib.rs | 1 + 6 files changed, 75 insertions(+), 92 deletions(-) create mode 100644 beacon_chain/genesis/Cargo.toml rename beacon_chain/{chain/src/genesis.rs => genesis/src/beacon_state.rs} (51%) create mode 100644 beacon_chain/genesis/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 856c2dae3f..963c5bc594 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ name = "lighthouse" members = [ "beacon_chain/attestation_validation", "beacon_chain/chain", + "beacon_chain/genesis", "beacon_chain/naive_fork_choice", "beacon_chain/spec", "beacon_chain/state-transition", diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index 5fc9dc0773..adfa682c79 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -9,7 +9,6 @@ extern crate validator_induction; extern crate validator_shuffling; mod block_processing; -mod genesis; mod maps; mod stores; mod transition; diff --git a/beacon_chain/genesis/Cargo.toml b/beacon_chain/genesis/Cargo.toml new file mode 100644 index 0000000000..f8708af1f0 --- /dev/null +++ b/beacon_chain/genesis/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "genesis" +version = "0.1.0" +authors = ["Paul Hauner "] + +[dependencies] +bls = { path = "../utils/bls" } +spec = { path = "../spec" } +types = { path = "../types" } +validator_induction = { path = "../validator_induction" } +validator_shuffling = { path = "../validator_shuffling" } diff --git a/beacon_chain/chain/src/genesis.rs b/beacon_chain/genesis/src/beacon_state.rs similarity index 51% rename from beacon_chain/chain/src/genesis.rs rename to beacon_chain/genesis/src/beacon_state.rs index 0444c9f294..d95136c6f2 100644 --- a/beacon_chain/chain/src/genesis.rs +++ b/beacon_chain/genesis/src/beacon_state.rs @@ -7,24 +7,16 @@ use validator_shuffling::{shard_and_committees_for_cycle, ValidatorAssignmentErr #[derive(Debug, PartialEq)] pub enum Error { + NoValidators, ValidationAssignmentError(ValidatorAssignmentError), NotImplemented, } -impl From for Error { - fn from(e: ValidatorAssignmentError) -> Error { - Error::ValidationAssignmentError(e) - } -} - -/// Initialize a new ChainHead with genesis parameters. -/// -/// Used when syncing a chain from scratch. -pub fn genesis_states( +pub fn genesis_beacon_state( spec: &ChainSpec, - initial_validators: Vec, + initial_validators: &[ValidatorRegistration], genesis_time: u64, - processed_pow_receipt_root: Hash256, + processed_pow_receipt_root: &Hash256, ) -> Result { /* * Parse the ValidatorRegistrations into ValidatorRecords and induct them. @@ -33,7 +25,7 @@ pub fn genesis_states( */ let validators = { let mut inductor = ValidatorInductor::new(0, spec.shard_count, vec![]); - for registration in &initial_validators { + for registration in initial_validators { let _ = inductor.induct(®istration, ValidatorStatus::Active); } inductor.to_vec() @@ -45,7 +37,7 @@ pub fn genesis_states( * Crystallizedstate stores two cycles, so we simply repeat the same assignment twice. */ let _shard_and_committee_for_slots = { - let mut a = shard_and_committees_for_cycle(&vec![0; 32], &validators, 0, &spec)?; + let mut a = shard_and_committees_for_cycle(&[0; 32], &validators, 0, &spec)?; let mut b = a.clone(); a.append(&mut b); a @@ -79,15 +71,15 @@ pub fn genesis_states( */ randao_mix: spec.zero_hash, next_seed: spec.zero_hash, - shard_committees_at_slot: vec![], + shard_committees_at_slots: vec![], persistent_committees: vec![], - persisten_committee_reassignments: vec![], + persistent_committee_reassignments: vec![], /* * Finality */ previous_justified_slot: spec.initial_slot_number, justified_slot: spec.initial_slot_number, - justified_bitfield: 0, + justification_bitfield: 0, finalized_slot: spec.initial_slot_number, /* * Recent state @@ -99,59 +91,28 @@ pub fn genesis_states( /* * PoW receipt root */ - processed_pow_receipt_root, + processed_pow_receipt_root: *processed_pow_receipt_root, candidate_pow_receipt_roots: vec![], }) } +impl From for Error { + fn from(e: ValidatorAssignmentError) -> Error { + Error::ValidationAssignmentError(e) + } +} + #[cfg(test)] mod tests { extern crate bls; extern crate validator_induction; - // TODO: implement genesis for `BeaconState` - // https://github.com/sigp/lighthouse/issues/99 - // - /* use self::bls::{create_proof_of_possession, Keypair}; use super::*; use types::{Address, Hash256, ValidatorRegistration}; - #[test] - fn test_genesis_no_validators() { - let config = ChainConfig::standard(); - let (act, cry) = genesis_states(&config).unwrap(); - - assert_eq!(cry.validator_set_change_slot, 0); - assert_eq!(cry.validators.len(), 0); - assert_eq!(cry.crosslinks.len(), config.shard_count as usize); - for cl in cry.crosslinks { - assert_eq!(cl.recently_changed, false); - assert_eq!(cl.slot, 0); - assert_eq!(cl.hash, Hash256::zero()); - } - assert_eq!(cry.last_state_recalculation_slot, 0); - assert_eq!(cry.last_finalized_slot, 0); - assert_eq!(cry.last_justified_slot, 0); - assert_eq!(cry.justified_streak, 0); - assert_eq!( - cry.shard_and_committee_for_slots.len(), - (config.cycle_length as usize) * 2 - ); - assert_eq!(cry.deposits_penalized_in_period.len(), 0); - assert_eq!(cry.validator_set_delta_hash_chain, Hash256::zero()); - assert_eq!(cry.pre_fork_version, INITIAL_FORK_VERSION); - assert_eq!(cry.post_fork_version, INITIAL_FORK_VERSION); - assert_eq!(cry.fork_slot_number, 0); - - assert_eq!(act.pending_attestations.len(), 0); - assert_eq!(act.pending_specials.len(), 0); - assert_eq!( - act.recent_block_hashes, - vec![Hash256::zero(); config.cycle_length as usize] - ); - assert_eq!(act.randao_mix, Hash256::zero()); - } + // TODO: enhance these tests. + // https://github.com/sigp/lighthouse/issues/117 fn random_registration() -> ValidatorRegistration { let keypair = Keypair::random(); @@ -164,45 +125,48 @@ mod tests { } } - #[test] - fn test_genesis_valid_validators() { - let mut config = ChainConfig::standard(); - let validator_count = 5; - - for _ in 0..validator_count { - config.initial_validators.push(random_registration()); + fn random_registrations(n: usize) -> Vec { + let mut output = Vec::with_capacity(n); + for _ in 0..n { + output.push(random_registration()) } - - let (_, cry) = genesis_states(&config).unwrap(); - - assert_eq!(cry.validators.len(), validator_count); + output } #[test] - fn test_genesis_invalid_validators() { - let mut config = ChainConfig::standard(); - let good_validator_count = 5; + fn test_genesis() { + let spec = ChainSpec::foundation(); + let genesis_time = 42; + let initial_validators = random_registrations(4); + let processed_pow_receipt_root = Hash256::from("pow_root".as_bytes()); - for _ in 0..good_validator_count { - config.initial_validators.push(random_registration()); - } + let state = genesis_beacon_state( + &spec, + &initial_validators, + genesis_time, + &processed_pow_receipt_root, + ).unwrap(); - let mut bad_v = random_registration(); - let bad_kp = Keypair::random(); - bad_v.proof_of_possession = create_proof_of_possession(&bad_kp); - config.initial_validators.push(bad_v); - - let mut bad_v = random_registration(); - bad_v.withdrawal_shard = config.shard_count + 1; - config.initial_validators.push(bad_v); - - let (_, cry) = genesis_states(&config).unwrap(); - - assert!( - config.initial_validators.len() != good_validator_count, - "test is invalid" - ); - assert_eq!(cry.validators.len(), good_validator_count); + assert_eq!(state.validator_registry.len(), 4); + } + + #[test] + fn test_genesis_bad_validator() { + let spec = ChainSpec::foundation(); + let genesis_time = 42; + let mut initial_validators = random_registrations(5); + let processed_pow_receipt_root = Hash256::from("pow_root".as_bytes()); + + let random_kp = Keypair::random(); + initial_validators[4].proof_of_possession = create_proof_of_possession(&random_kp); + + let state = genesis_beacon_state( + &spec, + &initial_validators, + genesis_time, + &processed_pow_receipt_root, + ).unwrap(); + + assert_eq!(state.validator_registry.len(), 4); } - */ } diff --git a/beacon_chain/genesis/src/lib.rs b/beacon_chain/genesis/src/lib.rs new file mode 100644 index 0000000000..54d45dae8f --- /dev/null +++ b/beacon_chain/genesis/src/lib.rs @@ -0,0 +1,7 @@ +extern crate spec; +extern crate types; +extern crate validator_induction; +extern crate validator_shuffling; + +pub mod beacon_state; + diff --git a/beacon_chain/spec/src/lib.rs b/beacon_chain/spec/src/lib.rs index a15575115b..e8f3cfdc30 100644 --- a/beacon_chain/spec/src/lib.rs +++ b/beacon_chain/spec/src/lib.rs @@ -4,6 +4,7 @@ mod foundation; use types::{Address, Hash256}; +#[derive(PartialEq, Debug)] pub struct ChainSpec { /* * Misc From 4f0a22357980a4282bff9a41a9ba4d559171ff03 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 12:28:37 +1100 Subject: [PATCH 07/14] Change some `ShardAndCommittee` -> `ShardCommittee` --- beacon_chain/types/src/crystallized_state.rs | 4 ++-- beacon_chain/types/src/shard_committee.rs | 2 +- beacon_chain/validator_shuffling/src/shuffle.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/beacon_chain/types/src/crystallized_state.rs b/beacon_chain/types/src/crystallized_state.rs index ff81202cf4..454454a17c 100644 --- a/beacon_chain/types/src/crystallized_state.rs +++ b/beacon_chain/types/src/crystallized_state.rs @@ -1,5 +1,5 @@ use super::crosslink_record::CrosslinkRecord; -use super::shard_and_committee::ShardAndCommittee; +use super::shard_committee::ShardCommittee; use super::validator_record::ValidatorRecord; use super::Hash256; @@ -12,7 +12,7 @@ pub struct CrystallizedState { pub last_finalized_slot: u64, pub last_justified_slot: u64, pub justified_streak: u64, - pub shard_and_committee_for_slots: Vec>, + pub shard_and_committee_for_slots: Vec>, pub deposits_penalized_in_period: Vec, pub validator_set_delta_hash_chain: Hash256, pub pre_fork_version: u32, diff --git a/beacon_chain/types/src/shard_committee.rs b/beacon_chain/types/src/shard_committee.rs index 2dc0f6a757..75208670f7 100644 --- a/beacon_chain/types/src/shard_committee.rs +++ b/beacon_chain/types/src/shard_committee.rs @@ -21,7 +21,7 @@ mod tests { #[test] fn test_shard_and_committee_zero() { - let s = ShardAndCommittee::zero(); + let s = ShardCommittee::zero(); assert_eq!(s.shard, 0); assert_eq!(s.committee.len(), 0); } diff --git a/beacon_chain/validator_shuffling/src/shuffle.rs b/beacon_chain/validator_shuffling/src/shuffle.rs index 3b3009e5d4..a9315e7268 100644 --- a/beacon_chain/validator_shuffling/src/shuffle.rs +++ b/beacon_chain/validator_shuffling/src/shuffle.rs @@ -3,10 +3,10 @@ use std::cmp::min; use active_validators::active_validator_indices; use honey_badger_split::SplitExt; use spec::ChainSpec; -use types::{ShardAndCommittee, ValidatorRecord}; +use types::{ShardCommittee, ValidatorRecord}; use vec_shuffle::{shuffle, ShuffleErr}; -type DelegatedCycle = Vec>; +type DelegatedCycle = Vec>; #[derive(Debug, PartialEq)] pub enum ValidatorAssignmentError { @@ -85,7 +85,7 @@ fn generate_cycle( slot_indices .honey_badger_split(committees_per_slot) .enumerate() - .map(|(j, shard_indices)| ShardAndCommittee { + .map(|(j, shard_indices)| ShardCommittee { shard: ((shard_start + j) % shard_count) as u16, committee: shard_indices.to_vec(), }).collect() From 06e1ee0e5f9a7d74fe0cca199ac034d38e0c3b1d Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 16:01:04 +1100 Subject: [PATCH 08/14] Add extra params to `ChainSpec` --- beacon_chain/genesis/src/beacon_state.rs | 71 ++++++------------------ beacon_chain/genesis/src/block.rs | 0 beacon_chain/genesis/src/lib.rs | 4 +- beacon_chain/spec/Cargo.toml | 1 + beacon_chain/spec/src/foundation.rs | 59 +++++++++++++++++++- beacon_chain/spec/src/lib.rs | 9 ++- 6 files changed, 87 insertions(+), 57 deletions(-) create mode 100644 beacon_chain/genesis/src/block.rs diff --git a/beacon_chain/genesis/src/beacon_state.rs b/beacon_chain/genesis/src/beacon_state.rs index d95136c6f2..fda94552fd 100644 --- a/beacon_chain/genesis/src/beacon_state.rs +++ b/beacon_chain/genesis/src/beacon_state.rs @@ -1,7 +1,5 @@ use spec::ChainSpec; -use types::{ - BeaconState, CrosslinkRecord, ForkData, Hash256, ValidatorRegistration, ValidatorStatus, -}; +use types::{BeaconState, CrosslinkRecord, ForkData, ValidatorStatus}; use validator_induction::ValidatorInductor; use validator_shuffling::{shard_and_committees_for_cycle, ValidatorAssignmentError}; @@ -12,12 +10,7 @@ pub enum Error { NotImplemented, } -pub fn genesis_beacon_state( - spec: &ChainSpec, - initial_validators: &[ValidatorRegistration], - genesis_time: u64, - processed_pow_receipt_root: &Hash256, -) -> Result { +pub fn genesis_beacon_state(spec: &ChainSpec) -> Result { /* * Parse the ValidatorRegistrations into ValidatorRecords and induct them. * @@ -25,7 +18,7 @@ pub fn genesis_beacon_state( */ let validators = { let mut inductor = ValidatorInductor::new(0, spec.shard_count, vec![]); - for registration in initial_validators { + for registration in &spec.initial_validators { let _ = inductor.induct(®istration, ValidatorStatus::Active); } inductor.to_vec() @@ -53,7 +46,7 @@ pub fn genesis_beacon_state( * Misc */ slot: spec.initial_slot_number, - genesis_time, + genesis_time: spec.genesis_time, fork_data: ForkData { pre_fork_version: spec.initial_fork_version, post_fork_version: spec.initial_fork_version, @@ -91,7 +84,7 @@ pub fn genesis_beacon_state( /* * PoW receipt root */ - processed_pow_receipt_root: *processed_pow_receipt_root, + processed_pow_receipt_root: spec.processed_pow_receipt_root, candidate_pow_receipt_roots: vec![], }) } @@ -109,64 +102,34 @@ mod tests { use self::bls::{create_proof_of_possession, Keypair}; use super::*; - use types::{Address, Hash256, ValidatorRegistration}; // TODO: enhance these tests. // https://github.com/sigp/lighthouse/issues/117 - fn random_registration() -> ValidatorRegistration { - let keypair = Keypair::random(); - ValidatorRegistration { - pubkey: keypair.pk.clone(), - withdrawal_shard: 0, - withdrawal_address: Address::random(), - randao_commitment: Hash256::random(), - proof_of_possession: create_proof_of_possession(&keypair), - } - } - - fn random_registrations(n: usize) -> Vec { - let mut output = Vec::with_capacity(n); - for _ in 0..n { - output.push(random_registration()) - } - output - } - #[test] fn test_genesis() { let spec = ChainSpec::foundation(); - let genesis_time = 42; - let initial_validators = random_registrations(4); - let processed_pow_receipt_root = Hash256::from("pow_root".as_bytes()); - let state = genesis_beacon_state( - &spec, - &initial_validators, - genesis_time, - &processed_pow_receipt_root, - ).unwrap(); + let state = genesis_beacon_state(&spec).unwrap(); - assert_eq!(state.validator_registry.len(), 4); + assert_eq!( + state.validator_registry.len(), + spec.initial_validators.len() + ); } #[test] fn test_genesis_bad_validator() { - let spec = ChainSpec::foundation(); - let genesis_time = 42; - let mut initial_validators = random_registrations(5); - let processed_pow_receipt_root = Hash256::from("pow_root".as_bytes()); + let mut spec = ChainSpec::foundation(); let random_kp = Keypair::random(); - initial_validators[4].proof_of_possession = create_proof_of_possession(&random_kp); + spec.initial_validators[4].proof_of_possession = create_proof_of_possession(&random_kp); - let state = genesis_beacon_state( - &spec, - &initial_validators, - genesis_time, - &processed_pow_receipt_root, - ).unwrap(); + let state = genesis_beacon_state(&spec).unwrap(); - assert_eq!(state.validator_registry.len(), 4); + assert_eq!( + state.validator_registry.len(), + spec.initial_validators.len() - 1 + ); } } diff --git a/beacon_chain/genesis/src/block.rs b/beacon_chain/genesis/src/block.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/beacon_chain/genesis/src/lib.rs b/beacon_chain/genesis/src/lib.rs index 54d45dae8f..3256ff5587 100644 --- a/beacon_chain/genesis/src/lib.rs +++ b/beacon_chain/genesis/src/lib.rs @@ -3,5 +3,7 @@ extern crate types; extern crate validator_induction; extern crate validator_shuffling; -pub mod beacon_state; +mod beacon_state; + +pub use beacon_state::genesis_beacon_state; diff --git a/beacon_chain/spec/Cargo.toml b/beacon_chain/spec/Cargo.toml index a2eac0692b..62ae74cc74 100644 --- a/beacon_chain/spec/Cargo.toml +++ b/beacon_chain/spec/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" authors = ["Paul Hauner "] [dependencies] +bls = { path = "../utils/bls" } types = { path = "../types" } diff --git a/beacon_chain/spec/src/foundation.rs b/beacon_chain/spec/src/foundation.rs index 5bf25e1e7a..b80187281a 100644 --- a/beacon_chain/spec/src/foundation.rs +++ b/beacon_chain/spec/src/foundation.rs @@ -1,9 +1,13 @@ use super::ChainSpec; +use bls::{create_proof_of_possession, Keypair, PublicKey, SecretKey}; -use types::{Address, Hash256}; +use types::{Address, Hash256, ValidatorRegistration}; impl ChainSpec { /// Returns a `ChainSpec` compatible with the specification from Ethereum Foundation. + /// + /// Of course, the actual foundation specs are unknown at this point so these are just a rough + /// estimate. pub fn foundation() -> Self { Self { /* @@ -56,6 +60,59 @@ impl ChainSpec { max_attestations: 128, max_deposits: 16, max_exits: 16, + /* + * Intialization parameters + */ + initial_validators: initial_validators_for_testing(), + genesis_time: 1544672897, + processed_pow_receipt_root: Hash256::from("pow_root".as_bytes()), } } } + +/// Generate a set of validator registrations to use with testing until the real chain starts. +fn initial_validators_for_testing() -> Vec { + // Some dummy private keys to start with. + let key_strings = vec![ + "jzjxxgjajfjrmgodszzsgqccmhnyvetcuxobhtynojtpdtbj", + "gpeehcjudxdijzhjgirfuhahmnjutlchjmoffxmimbdejakd", + "ntrrdwwebodokuwaclhoqreqyodngoyhurvesghjfxeswoaj", + "cibmzkqrzdgdlrvqaxinwpvyhcgjkeysrsjkqtkcxvznsvth", + "erqrfuahdwprsstkawggounxmihzhrvbhchcyiwtaypqcedr", + ]; + + let mut initial_validators = Vec::with_capacity(key_strings.len()); + for key_string in key_strings { + let keypair = { + let secret_key = match SecretKey::from_bytes(&key_string.as_bytes()) { + Ok(key) => key, + Err(_) => unreachable!(), // Keys are static and should not fail. + }; + let public_key = PublicKey::from_secret_key(&secret_key); + Keypair { + sk: secret_key, + pk: public_key, + } + }; + let validator_registration = ValidatorRegistration { + pubkey: keypair.pk.clone(), + withdrawal_shard: 0, + withdrawal_address: Address::random(), + randao_commitment: Hash256::random(), + proof_of_possession: create_proof_of_possession(&keypair), + }; + initial_validators.push(validator_registration); + } + + initial_validators +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_foundation_spec_can_be_constructed() { + let _ = ChainSpec::foundation(); + } +} diff --git a/beacon_chain/spec/src/lib.rs b/beacon_chain/spec/src/lib.rs index e8f3cfdc30..3a05f26967 100644 --- a/beacon_chain/spec/src/lib.rs +++ b/beacon_chain/spec/src/lib.rs @@ -1,8 +1,9 @@ +extern crate bls; extern crate types; mod foundation; -use types::{Address, Hash256}; +use types::{Address, Hash256, ValidatorRegistration}; #[derive(PartialEq, Debug)] pub struct ChainSpec { @@ -56,4 +57,10 @@ pub struct ChainSpec { pub max_attestations: u64, pub max_deposits: u64, pub max_exits: u64, + /* + * Intialization parameters + */ + pub initial_validators: Vec, + pub genesis_time: u64, + pub processed_pow_receipt_root: Hash256, } From 220a5bad7619cbf77546fd573f9ccfe9d859b246 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 17:32:17 +1100 Subject: [PATCH 09/14] Add clone method to some `types` --- beacon_chain/types/src/beacon_state.rs | 2 +- beacon_chain/types/src/candidate_pow_receipt_root_record.rs | 2 +- beacon_chain/types/src/shard_reassignment_record.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_chain/types/src/beacon_state.rs b/beacon_chain/types/src/beacon_state.rs index 03f2c93aaa..efd04b551c 100644 --- a/beacon_chain/types/src/beacon_state.rs +++ b/beacon_chain/types/src/beacon_state.rs @@ -7,7 +7,7 @@ use super::shard_reassignment_record::ShardReassignmentRecord; use super::validator_record::ValidatorRecord; use super::Hash256; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct BeaconState { // Misc pub slot: u64, diff --git a/beacon_chain/types/src/candidate_pow_receipt_root_record.rs b/beacon_chain/types/src/candidate_pow_receipt_root_record.rs index 9a1e3e5c82..a06e5e7943 100644 --- a/beacon_chain/types/src/candidate_pow_receipt_root_record.rs +++ b/beacon_chain/types/src/candidate_pow_receipt_root_record.rs @@ -1,6 +1,6 @@ use super::Hash256; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct CandidatePoWReceiptRootRecord { pub candidate_pow_receipt_root: Hash256, pub votes: u64, diff --git a/beacon_chain/types/src/shard_reassignment_record.rs b/beacon_chain/types/src/shard_reassignment_record.rs index 2f2c8a8d9f..c9a17741c7 100644 --- a/beacon_chain/types/src/shard_reassignment_record.rs +++ b/beacon_chain/types/src/shard_reassignment_record.rs @@ -1,4 +1,4 @@ -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ShardReassignmentRecord { pub validator_index: u64, pub shard: u64, From 96c20124344c9ba7992f24db1fd5a8754dd0f9ba Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 17:32:48 +1100 Subject: [PATCH 10/14] Add canonical_hash method to `BeaconState` --- beacon_chain/types/src/beacon_state.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/beacon_chain/types/src/beacon_state.rs b/beacon_chain/types/src/beacon_state.rs index efd04b551c..a3e83a5233 100644 --- a/beacon_chain/types/src/beacon_state.rs +++ b/beacon_chain/types/src/beacon_state.rs @@ -43,3 +43,11 @@ pub struct BeaconState { pub processed_pow_receipt_root: Hash256, pub candidate_pow_receipt_roots: Vec, } + +impl BeaconState { + pub fn canonical_root(&self) -> Hash256 { + // TODO: implement tree hashing. + // https://github.com/sigp/lighthouse/issues/70 + Hash256::zero() + } +} From 493a16ac182f72443a1d3301dd055f3e5adc6e05 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 17:33:16 +1100 Subject: [PATCH 11/14] Update attestation_validator for spec updates --- beacon_chain/attestation_validation/src/justified_slot.rs | 3 ++- beacon_chain/attestation_validation/src/shard_block.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/beacon_chain/attestation_validation/src/justified_slot.rs b/beacon_chain/attestation_validation/src/justified_slot.rs index c27dfe8f27..ea71f2616f 100644 --- a/beacon_chain/attestation_validation/src/justified_slot.rs +++ b/beacon_chain/attestation_validation/src/justified_slot.rs @@ -12,8 +12,9 @@ use super::{Error, Invalid, Outcome}; pub fn validate_attestation_justified_slot( data: &AttestationData, state: &BeaconState, + epoch_length: u64, ) -> Result { - let permissable_justified_slot = if data.slot >= state.latest_state_recalculation_slot { + let permissable_justified_slot = if data.slot >= state.slot - (state.slot % epoch_length) { state.justified_slot } else { state.previous_justified_slot diff --git a/beacon_chain/attestation_validation/src/shard_block.rs b/beacon_chain/attestation_validation/src/shard_block.rs index 7fb48ff627..e1d9487de8 100644 --- a/beacon_chain/attestation_validation/src/shard_block.rs +++ b/beacon_chain/attestation_validation/src/shard_block.rs @@ -19,7 +19,7 @@ where match state.latest_crosslinks.get(data.shard as usize) { None => reject!(Invalid::UnknownShard), Some(crosslink) => { - let local_shard_block_hash = crosslink.shard_block_hash; + let local_shard_block_hash = crosslink.shard_block_root; let shard_block_hash_is_permissable = { (local_shard_block_hash == data.latest_crosslink_hash) || (local_shard_block_hash == data.shard_block_hash) From 01f3b2f0c179e8b76b2c83141fac5bb26dd303c1 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Thu, 13 Dec 2018 17:33:53 +1100 Subject: [PATCH 12/14] Update `BeaconChain` w/ new genesis code --- beacon_chain/chain/Cargo.toml | 1 + beacon_chain/chain/src/lib.rs | 36 ++++++++++++++++------------ beacon_chain/chain/src/maps.rs | 16 ++++++------- beacon_chain/chain/src/transition.rs | 2 +- beacon_chain/genesis/src/lib.rs | 2 +- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/beacon_chain/chain/Cargo.toml b/beacon_chain/chain/Cargo.toml index 973e1560a0..f62a71b272 100644 --- a/beacon_chain/chain/Cargo.toml +++ b/beacon_chain/chain/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Paul Hauner "] [dependencies] bls = { path = "../utils/bls" } db = { path = "../../lighthouse/db" } +genesis = { path = "../genesis" } naive_fork_choice = { path = "../naive_fork_choice" } spec = { path = "../spec" } ssz = { path = "../utils/ssz" } diff --git a/beacon_chain/chain/src/lib.rs b/beacon_chain/chain/src/lib.rs index adfa682c79..1093347b9d 100644 --- a/beacon_chain/chain/src/lib.rs +++ b/beacon_chain/chain/src/lib.rs @@ -1,5 +1,6 @@ extern crate db; extern crate naive_fork_choice; +extern crate genesis; extern crate spec; extern crate ssz; extern crate ssz_helpers; @@ -14,12 +15,13 @@ mod stores; mod transition; use db::ClientDB; -use genesis::{genesis_states, Error as GenesisError}; +use genesis::{genesis_beacon_state, GenesisError}; use maps::{generate_attester_and_proposer_maps, AttesterAndProposerMapError}; +use spec::ChainSpec; use std::collections::HashMap; use std::sync::Arc; use stores::BeaconChainStore; -use types::{ActiveState, AttesterMap, ChainConfig, CrystallizedState, Hash256, ProposerMap}; +use types::{AttesterMap, BeaconState, Hash256, ProposerMap}; #[derive(Debug, PartialEq)] pub enum BeaconChainError { @@ -38,40 +40,45 @@ pub struct BeaconChain { /// The index of the canonical block in `head_block_hashes`. pub canonical_head_block_hash: usize, /// An in-memory map of root hash to beacon state. - pub beacon_states: HashMap, + pub beacon_states: HashMap, /// A map of crystallized state to a proposer and attester map. pub attester_proposer_maps: HashMap, Arc)>, /// A collection of database stores used by the chain. pub store: BeaconChainStore, /// The chain configuration. - pub config: ChainConfig, + pub spec: ChainSpec, } impl BeaconChain where T: ClientDB + Sized, { - pub fn new(store: BeaconChainStore, config: ChainConfig) -> Result { - if config.initial_validators.is_empty() { + pub fn new(store: BeaconChainStore, spec: ChainSpec) -> Result { + if spec.initial_validators.is_empty() { return Err(BeaconChainError::InsufficientValidators); } - let (active_state, crystallized_state) = genesis_states(&config)?; + /* + * Generate and process the genesis state. + */ + let genesis_state = genesis_beacon_state(&spec)?; + let mut beacon_states = HashMap::new(); + beacon_states.insert(genesis_state.canonical_root(), genesis_state.clone()); + // TODO: implement genesis block + // https://github.com/sigp/lighthouse/issues/105 let canonical_latest_block_hash = Hash256::zero(); + let head_block_hashes = vec![canonical_latest_block_hash]; let canonical_head_block_hash = 0; - let mut active_states = HashMap::new(); - let mut crystallized_states = HashMap::new(); + let mut attester_proposer_maps = HashMap::new(); let (attester_map, proposer_map) = generate_attester_and_proposer_maps( - &crystallized_state.shard_and_committee_for_slots, + &genesis_state.shard_committees_at_slots, 0, )?; - active_states.insert(canonical_latest_block_hash, active_state); - crystallized_states.insert(canonical_latest_block_hash, crystallized_state); attester_proposer_maps.insert( canonical_latest_block_hash, (Arc::new(attester_map), Arc::new(proposer_map)), @@ -81,11 +88,10 @@ where last_finalized_slot: 0, head_block_hashes, canonical_head_block_hash, - active_states, - crystallized_states, + beacon_states, attester_proposer_maps, store, - config, + spec, }) } diff --git a/beacon_chain/chain/src/maps.rs b/beacon_chain/chain/src/maps.rs index 9188531f28..cecd87c8d8 100644 --- a/beacon_chain/chain/src/maps.rs +++ b/beacon_chain/chain/src/maps.rs @@ -1,8 +1,8 @@ -use types::{AttesterMap, ProposerMap, ShardAndCommittee}; +use types::{AttesterMap, ProposerMap, ShardCommittee}; #[derive(Debug, PartialEq)] pub enum AttesterAndProposerMapError { - NoShardAndCommitteeForSlot, + NoShardCommitteeForSlot, NoAvailableProposer, } @@ -10,7 +10,7 @@ pub enum AttesterAndProposerMapError { /// /// The attester map is used to optimise the lookup of a committee. pub fn generate_attester_and_proposer_maps( - shard_and_committee_for_slots: &Vec>, + shard_and_committee_for_slots: &Vec>, start_slot: u64, ) -> Result<(AttesterMap, ProposerMap), AttesterAndProposerMapError> { let mut attester_map = AttesterMap::new(); @@ -22,7 +22,7 @@ pub fn generate_attester_and_proposer_maps( let slot_number = (i as u64).saturating_add(start_slot); let first_committee = &slot .get(0) - .ok_or(AttesterAndProposerMapError::NoShardAndCommitteeForSlot)? + .ok_or(AttesterAndProposerMapError::NoShardCommitteeForSlot)? .committee; let proposer_index = (slot_number as usize) .checked_rem(first_committee.len()) @@ -49,15 +49,15 @@ mod tests { slot_count: usize, sac_per_slot: usize, committee_size: usize, - ) -> Vec> { + ) -> Vec> { let mut shard = 0; let mut validator = 0; let mut cycle = vec![]; for _ in 0..slot_count { - let mut slot: Vec = vec![]; + let mut slot: Vec = vec![]; for _ in 0..sac_per_slot { - let mut sac = ShardAndCommittee { + let mut sac = ShardCommittee { shard: shard % shard_count, committee: vec![], }; @@ -79,7 +79,7 @@ mod tests { let result = generate_attester_and_proposer_maps(&sac, 0); assert_eq!( result, - Err(AttesterAndProposerMapError::NoShardAndCommitteeForSlot) + Err(AttesterAndProposerMapError::NoShardCommitteeForSlot) ); } diff --git a/beacon_chain/chain/src/transition.rs b/beacon_chain/chain/src/transition.rs index 7598f25175..df8803b27f 100644 --- a/beacon_chain/chain/src/transition.rs +++ b/beacon_chain/chain/src/transition.rs @@ -19,7 +19,7 @@ where .checked_sub(cry_state.last_state_recalculation_slot) .ok_or(StateTransitionError::BlockSlotBeforeRecalcSlot)?; - if state_recalc_distance >= u64::from(self.config.cycle_length) { + if state_recalc_distance >= u64::from(self.spec.epoch_length) { panic!("Not implemented!") } else { let new_act_state = extend_active_state(act_state, block, block_hash)?; diff --git a/beacon_chain/genesis/src/lib.rs b/beacon_chain/genesis/src/lib.rs index 3256ff5587..1f901e7a71 100644 --- a/beacon_chain/genesis/src/lib.rs +++ b/beacon_chain/genesis/src/lib.rs @@ -5,5 +5,5 @@ extern crate validator_shuffling; mod beacon_state; -pub use beacon_state::genesis_beacon_state; +pub use beacon_state::{genesis_beacon_state, Error as GenesisError}; From 3c4541156a8eb7b704063d2483af2904e11cbfc6 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Tue, 25 Dec 2018 19:25:48 +1100 Subject: [PATCH 13/14] Add BeaconBlock genesis --- beacon_chain/genesis/Cargo.toml | 1 + beacon_chain/genesis/src/beacon_block.rs | 38 ++++++++++++++++++++++++ beacon_chain/genesis/src/block.rs | 0 beacon_chain/genesis/src/lib.rs | 5 ++-- beacon_chain/types/src/beacon_block.rs | 4 +-- 5 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 beacon_chain/genesis/src/beacon_block.rs delete mode 100644 beacon_chain/genesis/src/block.rs diff --git a/beacon_chain/genesis/Cargo.toml b/beacon_chain/genesis/Cargo.toml index f8708af1f0..f1958eaa7d 100644 --- a/beacon_chain/genesis/Cargo.toml +++ b/beacon_chain/genesis/Cargo.toml @@ -2,6 +2,7 @@ name = "genesis" version = "0.1.0" authors = ["Paul Hauner "] +edition = "2018" [dependencies] bls = { path = "../utils/bls" } diff --git a/beacon_chain/genesis/src/beacon_block.rs b/beacon_chain/genesis/src/beacon_block.rs new file mode 100644 index 0000000000..9e2c75d24e --- /dev/null +++ b/beacon_chain/genesis/src/beacon_block.rs @@ -0,0 +1,38 @@ +use bls::Signature; +use spec::ChainSpec; +use types::{BeaconBlock, BeaconBlockBody}; + +/// Generate a genesis BeaconBlock. +pub fn genesis_beacon_block(spec: &ChainSpec) -> BeaconBlock { + BeaconBlock { + slot: spec.initial_slot_number, + parent_root: spec.zero_hash, + state_root: spec.zero_hash, + randao_reveal: spec.zero_hash, + candidate_pow_receipt_root: spec.zero_hash, + signature: Signature::default(), + body: BeaconBlockBody { + proposer_slashings: vec![], + casper_slashings: vec![], + attestations: vec![], + deposits: vec![], + exits: vec![], + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // TODO: enhance these tests. + // https://github.com/sigp/lighthouse/issues/117 + + #[test] + fn test_genesis() { + let spec = ChainSpec::foundation(); + + // This only checks that the function runs without panic. + genesis_beacon_block(&spec); + } +} diff --git a/beacon_chain/genesis/src/block.rs b/beacon_chain/genesis/src/block.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/beacon_chain/genesis/src/lib.rs b/beacon_chain/genesis/src/lib.rs index 1f901e7a71..e590fa8be8 100644 --- a/beacon_chain/genesis/src/lib.rs +++ b/beacon_chain/genesis/src/lib.rs @@ -4,6 +4,7 @@ extern crate validator_induction; extern crate validator_shuffling; mod beacon_state; +mod beacon_block; -pub use beacon_state::{genesis_beacon_state, Error as GenesisError}; - +pub use crate::beacon_block::genesis_beacon_block; +pub use crate::beacon_state::{genesis_beacon_state, Error as GenesisError}; diff --git a/beacon_chain/types/src/beacon_block.rs b/beacon_chain/types/src/beacon_block.rs index b6ac9e9e02..36b625eb57 100644 --- a/beacon_chain/types/src/beacon_block.rs +++ b/beacon_chain/types/src/beacon_block.rs @@ -1,7 +1,7 @@ use super::ssz::{Decodable, DecodeError, Encodable, SszStream}; use super::{BeaconBlockBody, Hash256}; use crate::test_utils::TestRandom; -use bls::AggregateSignature; +use bls::Signature; use rand::RngCore; #[derive(Debug, PartialEq, Clone, Default)] @@ -11,7 +11,7 @@ pub struct BeaconBlock { pub state_root: Hash256, pub randao_reveal: Hash256, pub candidate_pow_receipt_root: Hash256, - pub signature: AggregateSignature, + pub signature: Signature, pub body: BeaconBlockBody, } From d79d0182a6e981dc6d561dcf87de09978a3be534 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 26 Dec 2018 11:15:51 +1100 Subject: [PATCH 14/14] Implement genesis signature --- beacon_chain/genesis/Cargo.toml | 1 + beacon_chain/genesis/src/beacon_block.rs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/beacon_chain/genesis/Cargo.toml b/beacon_chain/genesis/Cargo.toml index f1958eaa7d..4993339797 100644 --- a/beacon_chain/genesis/Cargo.toml +++ b/beacon_chain/genesis/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] bls = { path = "../utils/bls" } spec = { path = "../spec" } +ssz = { path = "../utils/ssz" } types = { path = "../types" } validator_induction = { path = "../validator_induction" } validator_shuffling = { path = "../validator_shuffling" } diff --git a/beacon_chain/genesis/src/beacon_block.rs b/beacon_chain/genesis/src/beacon_block.rs index 9e2c75d24e..120903564a 100644 --- a/beacon_chain/genesis/src/beacon_block.rs +++ b/beacon_chain/genesis/src/beacon_block.rs @@ -1,5 +1,6 @@ -use bls::Signature; +use bls::{Signature, BLS_AGG_SIG_BYTE_SIZE}; use spec::ChainSpec; +use ssz::{encode::encode_length, Decodable, LENGTH_BYTES}; use types::{BeaconBlock, BeaconBlockBody}; /// Generate a genesis BeaconBlock. @@ -10,7 +11,7 @@ pub fn genesis_beacon_block(spec: &ChainSpec) -> BeaconBlock { state_root: spec.zero_hash, randao_reveal: spec.zero_hash, candidate_pow_receipt_root: spec.zero_hash, - signature: Signature::default(), + signature: genesis_signature(), body: BeaconBlockBody { proposer_slashings: vec![], casper_slashings: vec![], @@ -21,6 +22,16 @@ pub fn genesis_beacon_block(spec: &ChainSpec) -> BeaconBlock { } } +fn genesis_signature() -> Signature { + let mut bytes = encode_length(BLS_AGG_SIG_BYTE_SIZE, LENGTH_BYTES); + bytes.append(&mut vec![0; BLS_AGG_SIG_BYTE_SIZE]); + let (signature, _) = match Signature::ssz_decode(&bytes, 0) { + Ok(sig) => sig, + Err(_) => unreachable!(), + }; + signature +} + #[cfg(test)] mod tests { use super::*;