From ca40229cb4bcac40db651a9bbcd8cde219d23ca0 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Mon, 16 Jul 2018 11:57:32 +1000 Subject: [PATCH] Implement increment_validator_sets() --- src/state/transition/mod.rs | 2 + src/state/transition/validators.rs | 171 +++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 src/state/transition/validators.rs diff --git a/src/state/transition/mod.rs b/src/state/transition/mod.rs index d837261e9..155a54179 100644 --- a/src/state/transition/mod.rs +++ b/src/state/transition/mod.rs @@ -4,7 +4,9 @@ use super::blake2; use super::crystallized_state; use super::crosslink_record; use super::partial_crosslink_record; +use super::validator_record; pub mod crosslinks; pub mod deposits; pub mod shuffling; +pub mod validators; diff --git a/src/state/transition/validators.rs b/src/state/transition/validators.rs new file mode 100644 index 000000000..79c728aca --- /dev/null +++ b/src/state/transition/validators.rs @@ -0,0 +1,171 @@ +use std::cmp::min; + +use super::crystallized_state::CrystallizedState; +use super::validator_record::ValidatorRecord; +use super::config::Config; + +pub fn get_incremented_validator_sets( + cry_state: &CrystallizedState, + active_validators: &Vec, + config: &Config) + -> (Vec, Vec, Vec) +{ + let mut new_active_validators: Vec = vec![]; + let mut new_exited_validators: Vec + = cry_state.exited_validators.clone(); + let next_dynasty = cry_state.dynasty + 1; + + for v in active_validators { + if (v.balance <= config.eject_balance) | + (v.switch_dynasty == next_dynasty) { + new_exited_validators.push(v.clone()); + } + else { + new_active_validators.push(v.clone()); + } + } + + let induction_count = min( + cry_state.num_queued_validators(), + cry_state.num_active_validators() / 30 + 1); + let mut first_ineligable = induction_count; + for i in 0..induction_count { + if cry_state.queued_validators[i].switch_dynasty > next_dynasty { + first_ineligable = i; + break; + } + new_active_validators.push(cry_state.queued_validators[i].clone()); + } + let new_queued_validators = cry_state. + queued_validators[first_ineligable..cry_state.queued_validators.len()] + .to_vec(); + (new_queued_validators, new_active_validators, new_exited_validators) +} + +#[cfg(test)] +mod tests { + use super::*; + use super::super::utils::types::U256; + // use super::super::shuffling::get_shuffling; + + fn test_setup() -> (CrystallizedState, Config) { + let mut cry_state = CrystallizedState::zero(); + let mut config = Config::standard(); + + config.shard_count = 5; + config.notaries_per_crosslink = 2; + config.default_balance = U256::from(32000); + config.eject_balance = U256::from(16000); + cry_state.current_epoch = 100; + cry_state.dynasty = 100; + (cry_state, config) + } + + #[test] + fn test_incrementing_validator_sets_scenario_1() { + let (mut cry_state, config) = test_setup(); + let validator_count = 10; + + let mut a: Vec = vec![]; + let mut q: Vec = vec![]; + let mut x: Vec = vec![]; + + (0..validator_count).for_each(|_| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + v.switch_dynasty = cry_state.dynasty + 5; + v.balance = config.default_balance.clone(); + a.push(v) + }); + + (0..validator_count).for_each(|_| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + v.switch_dynasty = cry_state.dynasty + 1; + v.balance = config.default_balance.clone(); + q.push(v) + }); + + (0..validator_count).for_each(|_| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + v.switch_dynasty = cry_state.dynasty - 1; + v.balance = config.default_balance.clone(); + x.push(v) + }); + + cry_state.active_validators = a.to_vec(); + cry_state.queued_validators = q.to_vec(); + cry_state.exited_validators = x.to_vec(); + + let (nq, na, nx) = get_incremented_validator_sets( + &cry_state, + &a, + &config); + + let inducted = validator_count / 30 + 1; + assert!(inducted > 0); + + assert_eq!(na.len(), validator_count + inducted, "new active incorrect"); + assert_eq!(nq.len(), validator_count - inducted, "new queued incorrect"); + assert_eq!(nx.len(), validator_count, "new exited incorrect"); + } + + #[test] + fn test_incrementing_validator_sets_scenario_2() { + let (mut cry_state, config) = test_setup(); + let validator_count = 60; + let expiring_active = 5; + let eligable_queued = 1; + + let mut a: Vec = vec![]; + let mut q: Vec = vec![]; + let mut x: Vec = vec![]; + + (0..validator_count).for_each(|i| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + if i < expiring_active { + v.switch_dynasty = cry_state.dynasty + 1; + } else { + v.switch_dynasty = cry_state.dynasty + 5; + } + v.balance = config.default_balance.clone(); + a.push(v) + }); + + (0..validator_count).for_each(|i| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + if i < eligable_queued { + v.switch_dynasty = cry_state.dynasty + 1; + } else { + v.switch_dynasty = cry_state.dynasty + 5; + } + v.balance = config.default_balance.clone(); + q.push(v) + }); + + (0..validator_count).for_each(|_| { + let mut v = ValidatorRecord::zero_with_thread_rand_pub_key(); + v.switch_dynasty = cry_state.dynasty - 1; + v.balance = config.default_balance.clone(); + x.push(v) + }); + + cry_state.active_validators = a.to_vec(); + cry_state.queued_validators = q.to_vec(); + cry_state.exited_validators = x.to_vec(); + + let (nq, na, nx) = get_incremented_validator_sets( + &cry_state, + &a, + &config); + + let inducted = validator_count / 30 + 1; + assert!(inducted > eligable_queued, "this test requires more inductable \ + validators than there are eligable."); + + assert_eq!(na.len(), validator_count - expiring_active + eligable_queued, + "new active incorrect"); + assert_eq!(nq.len(), validator_count - eligable_queued, + "new queued incorrect"); + assert_eq!(nx.len(), validator_count + expiring_active, + "new exited incorrect"); + } +}