diff --git a/src/state/state_transition.rs b/src/state/state_transition.rs index a9f1c41ba..baf70c8e3 100644 --- a/src/state/state_transition.rs +++ b/src/state/state_transition.rs @@ -1,4 +1,3 @@ -use super::utils::types::{ Bitfield, U256 }; use super::bytes::{ BytesMut, BufMut }; use super::crystallized_state::CrystallizedState; use super::active_state::ActiveState; @@ -54,46 +53,11 @@ pub fn get_attesters_and_proposer( } } -pub fn process_ffg_deposits( - cry_state: &CrystallizedState, - ffg_vote_bitfield: Bitfield) - -> (Vec, u64, U256, bool, bool) -{ - let active_validators: usize = cry_state.num_active_validators(); - let finality_distance: u64 = cry_state.finality_distance(); - let online_reward: u64 = if finality_distance <= 2 { 6 } else { 0 }; - let offline_penalty: u64 = finality_distance.saturating_mul(3); - let mut total_vote_count: u64 = 0; - let mut total_vote_deposits = U256::zero(); - - let mut deltas = vec![0_u64; active_validators]; - for i in 0..active_validators { - if ffg_vote_bitfield.get_bit(&i) { - total_vote_deposits = total_vote_deposits - .saturating_add(cry_state.active_validators[i].balance); - deltas[i] += online_reward; - total_vote_count += 1; - } else { - deltas[i] = deltas[i].saturating_sub(offline_penalty); - } - } - - let mut should_finalize = false; - let should_justify = total_vote_deposits.saturating_mul(U256::from(3)) - >= cry_state.total_deposits.saturating_mul(U256::from(2)); - if should_justify { - if cry_state.last_justified_epoch == cry_state.current_epoch - 1 { - should_finalize = true; - } - } - (deltas, total_vote_count, total_vote_deposits, should_justify, should_finalize) -} - #[cfg(test)] mod tests { use super::*; use super::super::validator_record::ValidatorRecord; - use super::super::utils::types::{ Address, Sha256Digest }; + use super::super::utils::types::{ Address, Sha256Digest, U256 }; use super::super:: utils::test_helpers::get_dangerous_test_keypair; diff --git a/src/state/transition/deposits.rs b/src/state/transition/deposits.rs new file mode 100644 index 000000000..d181bae34 --- /dev/null +++ b/src/state/transition/deposits.rs @@ -0,0 +1,122 @@ +use super::crystallized_state::CrystallizedState; +use super::utils::types::{ Bitfield, U256 }; + +pub fn process_ffg_deposits( + cry_state: &CrystallizedState, + ffg_vote_bitfield: &Bitfield) + -> (Vec, u64, U256, bool, bool) +{ + let active_validators: usize = cry_state.num_active_validators(); + let finality_distance: u64 = cry_state.finality_distance(); + let online_reward: u64 = if finality_distance <= 2 { 6 } else { 0 }; + let offline_penalty: u64 = finality_distance.saturating_mul(3); + let mut total_vote_count: u64 = 0; + let mut total_vote_deposits = U256::zero(); + + let mut deltas = vec![0_i64; active_validators]; + for i in 0..active_validators { + if ffg_vote_bitfield.get_bit(&i) { + total_vote_deposits = total_vote_deposits + .saturating_add(cry_state.active_validators[i].balance); + deltas[i] += online_reward as i64; + total_vote_count += 1; + } else { + deltas[i] -= offline_penalty as i64; + } + } + + // Justify if total voting deposits is greater than 2/3 the total deposits. + let should_justify = total_vote_deposits.saturating_mul(U256::from(3)) + >= cry_state.total_deposits.saturating_mul(U256::from(2)); + let mut should_finalize = false; + if should_justify { + if cry_state.last_justified_epoch == cry_state.current_epoch - 1 { + should_finalize = true; + } + } + (deltas, total_vote_count, total_vote_deposits, should_justify, should_finalize) +} + +#[cfg(test)] +mod tests { + use super::*; + use super::super::utils::types::{ Address, Sha256Digest }; + use super::super::super::validator_record::ValidatorRecord; + use super::super:: + utils::test_helpers::get_dangerous_test_keypair; + + #[test] + fn test_deposit_processing_scenario_1() { + let mut cry_state = CrystallizedState::zero(); + let mut bitfield = Bitfield::new(); + let mut total_deposits = U256::zero(); + let individual_deposit = U256::from(1); + + + // load some validators into the cry state and flag + // they have all voted + for i in 0..10 { + cry_state.active_validators.push(ValidatorRecord { + pubkey: get_dangerous_test_keypair().public, + withdrawal_shard: 0, + withdrawal_address: Address::zero(), + randao_commitment: Sha256Digest::zero(), + balance: individual_deposit, + switch_dynasty: 0 + }); + total_deposits = total_deposits + individual_deposit; + bitfield.set_bit(&i, &true); + } + + cry_state.current_epoch = 100; + cry_state.last_justified_epoch = 99; + cry_state.last_finalized_epoch = 98; + cry_state.total_deposits = total_deposits; + + let (deltas, total_vote_count, total_vote_deposits, + should_justify, should_finalize) = process_ffg_deposits( + &cry_state, &bitfield); + + assert_eq!(deltas, [6; 10]); + assert_eq!(total_vote_count, 10); + assert_eq!(total_vote_deposits, total_deposits); + assert_eq!(should_justify, true); + assert_eq!(should_finalize, true); + } + + #[test] + fn test_deposit_processing_scenario_2() { + let mut cry_state = CrystallizedState::zero(); + let bitfield = Bitfield::new(); + let individual_deposit = U256::from(0); + + + // load some validators into the cry state and flag + // they have all voted + for _i in 0..10 { + cry_state.active_validators.push(ValidatorRecord { + pubkey: get_dangerous_test_keypair().public, + withdrawal_shard: 0, + withdrawal_address: Address::zero(), + randao_commitment: Sha256Digest::zero(), + balance: individual_deposit, + switch_dynasty: 0 + }); + } + + cry_state.current_epoch = 100; + cry_state.last_justified_epoch = 99; + cry_state.last_finalized_epoch = 98; + cry_state.total_deposits = U256::from(10); + + let (deltas, total_vote_count, total_vote_deposits, + should_justify, should_finalize) = process_ffg_deposits( + &cry_state, &bitfield); + + assert_eq!(deltas, [-6; 10]); + assert_eq!(total_vote_count, 0); + assert_eq!(total_vote_deposits, U256::zero()); + assert_eq!(should_justify, false); + assert_eq!(should_finalize, false); + } +} diff --git a/src/state/transition/mod.rs b/src/state/transition/mod.rs index 2f722f2de..6f2308f3c 100644 --- a/src/state/transition/mod.rs +++ b/src/state/transition/mod.rs @@ -1,5 +1,7 @@ use super::config; use super::utils; use super::blake2; +use super::crystallized_state; pub mod shuffling; +pub mod deposits;