From faaba18799750d83d76181a7d2ceb13c9c8bcce4 Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Thu, 20 Dec 2018 20:22:08 -0600 Subject: [PATCH] types updated against spec and process_deposit routine partially implemented --- beacon_chain/types/src/beacon_state.rs | 12 +- beacon_chain/types/src/validator_record.rs | 2 - beacon_chain/validator_induction/Cargo.toml | 1 + .../validator_induction/src/inductor.rs | 202 +++++++----------- beacon_chain/validator_induction/src/lib.rs | 3 +- 5 files changed, 92 insertions(+), 128 deletions(-) diff --git a/beacon_chain/types/src/beacon_state.rs b/beacon_chain/types/src/beacon_state.rs index d0e46f1b5..76c23ac85 100644 --- a/beacon_chain/types/src/beacon_state.rs +++ b/beacon_chain/types/src/beacon_state.rs @@ -9,7 +9,11 @@ use super::Hash256; #[derive(Debug, PartialEq, Default)] pub struct BeaconState { + pub slot: u64, + pub genesis_time: u64, + pub fork_data: ForkData, pub validator_registry: Vec, + pub validator_balances: Vec, pub validator_registry_latest_change_slot: u64, pub validator_registry_exit_count: u64, pub validator_registry_delta_chain_tip: Hash256, @@ -20,15 +24,13 @@ pub struct BeaconState { pub persistent_committee_reassignments: Vec, pub previous_justified_slot: u64, pub justified_slot: u64, - pub justified_slot_bitfield: u64, + pub justification_bitfield: u64, pub finalized_slot: u64, 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, + pub batched_block_roots: Vec, 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/validator_record.rs b/beacon_chain/types/src/validator_record.rs index b8834131f..af0e75d39 100644 --- a/beacon_chain/types/src/validator_record.rs +++ b/beacon_chain/types/src/validator_record.rs @@ -32,7 +32,6 @@ pub struct ValidatorRecord { pub withdrawal_credentials: Hash256, pub randao_commitment: Hash256, pub randao_layers: u64, - pub balance: u64, pub status: ValidatorStatus, pub latest_status_change_slot: u64, pub exit_count: u64 @@ -50,7 +49,6 @@ impl ValidatorRecord { withdrawal_credentials: Hash256::zero(), randao_commitment: Hash256::zero(), randao_layers: 0, - balance: 0, status: From::from(0), latest_status_change_slot: 0, exit_count: 0 diff --git a/beacon_chain/validator_induction/Cargo.toml b/beacon_chain/validator_induction/Cargo.toml index 9a443133e..2236b0f63 100644 --- a/beacon_chain/validator_induction/Cargo.toml +++ b/beacon_chain/validator_induction/Cargo.toml @@ -7,3 +7,4 @@ authors = ["Paul Hauner "] bls = { path = "../utils/bls" } hashing = { path = "../utils/hashing" } types = { path = "../types" } +spec = { path = "../spec" } diff --git a/beacon_chain/validator_induction/src/inductor.rs b/beacon_chain/validator_induction/src/inductor.rs index 08a738158..36bce4284 100644 --- a/beacon_chain/validator_induction/src/inductor.rs +++ b/beacon_chain/validator_induction/src/inductor.rs @@ -1,111 +1,76 @@ -use bls::verify_proof_of_possession; -use types::{ValidatorRecord, DepositInput, ValidatorStatus, BeaconState}; +use bls::{PublicKey, verify_proof_of_possession}; +use types::{BeaconState, Deposit, ValidatorRecord, ValidatorStatus}; +use spec::ChainSpec; /// The size of a validators deposit in GWei. 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, - beacon_state: BeaconState, - empty_validator_start: usize, -} - #[derive(Debug, PartialEq, Clone)] pub enum ValidatorInductionError { InvalidShard, InvaidProofOfPossession, + InvalidWithdrawalCredentials } -impl ValidatorInductor { - pub fn new(current_slot: u64, shard_count: u16, beacon_state: BeaconState) -> Self { - Self { - current_slot, - shard_count, - beacon_state, - empty_validator_start: 0, - } - } - - /// Attempt to induct a validator into the CrystallizedState. - /// - /// Returns an error if the registration is invalid, otherwise returns the index of the - /// validator in `CrystallizedState.validators`. - pub fn induct( - &mut self, - deposit_input: &DepositInput, - status: ValidatorStatus, - ) -> Result { - let v = self.process_deposit(deposit_input, status)?; - Ok(self.add_validator(v)) - } - - /// Verify a `ValidatorRegistration` and return a `ValidatorRecord` if valid. - fn process_deposit( - &self, - deposit_input: &DepositInput, - status: ValidatorStatus, - ) -> Result { - /* - * Ensure withdrawal shard is not too high. - */ - /* - if r.withdrawal_shard > self.shard_count { - return Err(ValidatorInductionError::InvalidShard); - } - */ - - /* - * Prove validator has knowledge of their secret key. - */ - if !verify_proof_of_possession(&deposit_input.proof_of_possession, &deposit_input.pubkey) { - return Err(ValidatorInductionError::InvaidProofOfPossession); - } - - Ok(ValidatorRecord { - pubkey: deposit_input.pubkey.clone(), - withdrawal_credentials: deposit_input.withdrawal_credentials, - randao_commitment: deposit_input.randao_commitment, - randao_layers: 0, - balance: DEPOSIT_GWEI, - status: status, - latest_status_change_slot: self.beacon_state.validator_registry_latest_change_slot, - exit_count: 0 - }) - } - - /// Returns the index of the first `ValidatorRecord` in the `CrystallizedState` where - /// `validator.status == Withdrawn`. If no such record exists, `None` is returned. - fn first_withdrawn_validator(&mut self) -> Option { - for i in self.empty_validator_start..self.beacon_state.validator_registry.len() { - if self.beacon_state.validator_registry[i].status == ValidatorStatus::Withdrawn { - self.empty_validator_start = i + 1; - return Some(i); +pub fn process_deposit( + state: &mut BeaconState, + deposit: &Deposit, + spec: &ChainSpec) +-> Result { + let deposit_input = &deposit.deposit_data.deposit_input; + let validator_index = state.validator_registry.iter() + .position(|validator| validator.pubkey == deposit_input.pubkey); + + match validator_index { + // replace withdrawn validator + Some(i) => { + if state.validator_registry[i].withdrawal_credentials == deposit_input.withdrawal_credentials { + state.validator_balances[i] += DEPOSIT_GWEI; + return Ok(i); } - } - None - } - - /// Adds a `ValidatorRecord` to the `CrystallizedState` by replacing first validator where - /// `validator.status == Withdraw`. If no such withdrawn validator exists, adds the new - /// validator to the end of the list. - fn add_validator(&mut self, v: ValidatorRecord) -> usize { - match self.first_withdrawn_validator() { - Some(i) => { - self.beacon_state.validator_registry[i] = v; - i - } - None => { - self.beacon_state.validator_registry.push(v); - self.beacon_state.validator_registry.len() - 1 + + Err(ValidatorInductionError::InvalidWithdrawalCredentials) + }, + // no withdrawn validators; push a new one on + None => { + let validator = ValidatorRecord { + pubkey: deposit_input.pubkey.clone(), + withdrawal_credentials: deposit_input.withdrawal_credentials, + randao_commitment: deposit_input.randao_commitment, + randao_layers: 0, + status: ValidatorStatus::PendingActivation, + latest_status_change_slot: state.validator_registry_latest_change_slot.clone(), + exit_count: 0 + }; + + match min_empty_validator_index(state, spec) { + Some(i) => { + state.validator_registry[i] = validator; + state.validator_balances[i] = DEPOSIT_GWEI; + Ok(i) + }, + None => { + state.validator_registry.push(validator); + state.validator_balances.push(DEPOSIT_GWEI); + Ok(state.validator_registry.len() - 1) + } } } } +} - pub fn to_vec(self) -> Vec { - self.beacon_state.validator_registry +fn min_empty_validator_index( + state: &BeaconState, + spec: &ChainSpec +) -> Option { + for i in 0..state.validator_registry.len() { + if state.validator_balances[i] == 0 + && state.validator_registry[i].latest_status_change_slot + + spec.zero_balance_validator_ttl <= state.slot { + return Some(i); + } } + None } #[cfg(test)] @@ -114,17 +79,27 @@ mod tests { use bls::{Keypair, Signature}; use hashing::proof_of_possession_hash; - use types::{Hash256}; - - /* - fn registration_equals_record(reg: &ValidatorRegistration, rec: &ValidatorRecord) -> bool { - (reg.pubkey == rec.pubkey) - & (reg.withdrawal_shard == rec.withdrawal_shard) - & (reg.withdrawal_address == rec.withdrawal_address) - & (reg.randao_commitment == rec.randao_commitment) - & (verify_proof_of_possession(®.proof_of_possession, &rec.pubkey)) + use types::{Hash256, DepositData, DepositInput}; + + fn get_deposit() -> Deposit { + let kp = Keypair::random(); + let deposit_input = DepositInput { + pubkey: kp.pk.clone(), + withdrawal_credentials: Hash256::zero(), + randao_commitment: Hash256::zero(), + proof_of_possession: get_proof_of_possession(&kp) + }; + let deposit_data = DepositData { + deposit_input: deposit_input, + value: 0, + timestamp: 0 + }; + Deposit { + merkle_branch: Vec::new(), + merkle_tree_index: 0, + deposit_data: deposit_data + } } - */ /// Generate a proof of possession for some keypair. fn get_proof_of_possession(kp: &Keypair) -> Signature { @@ -132,30 +107,17 @@ mod tests { Signature::new_hashed(&pop_message, &kp.sk) } - /// Generate a basic working Deposit for use in tests. - fn get_deposit_input() -> DepositInput { - let kp = Keypair::random(); - DepositInput { - pubkey: kp.pk.clone(), - withdrawal_credentials: Hash256::zero(), - randao_commitment: Hash256::zero(), - proof_of_possession: get_proof_of_possession(&kp) - } - } - #[test] fn test_validator_inductor_valid_empty_validators() { - let state = BeaconState::default(); + let mut state = BeaconState::default(); + let deposit = get_deposit(); + let spec = ChainSpec::foundation(); - let d = get_deposit_input(); - - let mut inductor = ValidatorInductor::new(0, 1024, state); - let result = inductor.induct(&d, ValidatorStatus::PendingActivation); - let validators = inductor.to_vec(); + let result = process_deposit(&mut state, &deposit, &spec); assert_eq!(result.unwrap(), 0); //assert!(registration_equals_record(&r, &validators[0])); - assert_eq!(validators.len(), 1); + //assert_eq!(validators.len(), 1); } /* diff --git a/beacon_chain/validator_induction/src/lib.rs b/beacon_chain/validator_induction/src/lib.rs index 6ea6265ba..582155555 100644 --- a/beacon_chain/validator_induction/src/lib.rs +++ b/beacon_chain/validator_induction/src/lib.rs @@ -1,7 +1,8 @@ extern crate bls; extern crate hashing; extern crate types; +extern crate spec; mod inductor; -pub use inductor::{ValidatorInductionError, ValidatorInductor}; +pub use inductor::{ValidatorInductionError};