-
Notifications
You must be signed in to change notification settings - Fork 65
feat: add BeaconState functions/mutators #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| /// Decrease the validator balance at index ``index`` by ``delta`` with underflow protection. | ||
| pub fn decrease_balance(mut self, index: u64, delta: u64) { | ||
| if let Some(balance) = self.balances.get_mut(index as usize) { | ||
| *balance -= delta; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| *balance -= delta; | |
| balance.saturating_sub(delta) |
the comment says underflow protection, I am assuming that would be a saturating sub?
| } | ||
|
|
||
| /// Decrease the validator balance at index ``index`` by ``delta`` with underflow protection. | ||
| pub fn decrease_balance(mut self, index: u64, delta: u64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pub fn decrease_balance(mut self, index: u64, delta: u64) { | |
| pub fn decrease_balance(&mut self, index: u64, delta: u64) { |
c90506b to
ab3448d
Compare
KolbyML
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is some more feedback
| let current_epoch = self.get_current_epoch(); | ||
| let mut exit_queue_epoch = exit_epochs | ||
| .into_iter() | ||
| .max() | ||
| .unwrap_or_else(|| compute_activation_exit_epoch(current_epoch)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let current_epoch = self.get_current_epoch(); | |
| let mut exit_queue_epoch = exit_epochs | |
| .into_iter() | |
| .max() | |
| .unwrap_or_else(|| compute_activation_exit_epoch(current_epoch)); | |
| let mut exit_queue_epoch = exit_epochs | |
| .into_iter() | |
| .max() | |
| .unwrap_or_else(|| compute_activation_exit_epoch(self.get_current_epoch())); |
this isn't reused it should be inlined
| let current_epoch = self.get_current_epoch(); | ||
| let mut exit_queue_epoch = exit_epochs | ||
| .into_iter() | ||
| .max() | ||
| .unwrap_or_else(|| compute_activation_exit_epoch(current_epoch)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't follow the spec no?
| let current_epoch = self.get_current_epoch(); | |
| let mut exit_queue_epoch = exit_epochs | |
| .into_iter() | |
| .max() | |
| .unwrap_or_else(|| compute_activation_exit_epoch(current_epoch)); | |
| let current_epoch = self.get_current_epoch(); | |
| let mut exit_queue_epoch = max(exit_epochs, vec![compute_activation_exit_epoch(self.get_current_epoch())]); |
I think this would match the spec better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This however returns a Vec instead of just a u64
This feels a more suitable approach:
exit_epochs.push(compute_activation_exit_epoch(self.get_current_epoch()));
let mut exit_queue_epoch = *exit_epochs.iter().max().unwrap_or(&0);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good
| if index as usize >= self.validators.len() { | ||
| return; | ||
| } | ||
| let exit_epochs: Vec<u64> = self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aren't you missing this check
if validator.exit_epoch != FAR_FUTURE_EPOCH:
return
| slashed_index: usize, | ||
| whistleblower_index: Option<usize>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| slashed_index: usize, | |
| whistleblower_index: Option<usize>, | |
| slashed_index: u64, | |
| whistleblower_index: Option<u64>, |
these should be u64's as that is how they are defined in the spec, also then there will be less type conversions in this function so it will be cleaner to read
| } | ||
|
|
||
| /// Slash the validator with index ``slashed_index`` | ||
| pub fn slash_validator( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is outdated, please update it to follow the latest version of the spec https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#modified-slash_validator
| pub const SLOTS_PER_HISTORICAL_ROOT: u64 = 8192; | ||
| pub const MIN_SEED_LOOKAHEAD: u64 = 1; | ||
| pub const MAX_COMMITTEES_PER_SLOT: u64 = 64; | ||
| pub const WHISTLEBLOWER_REWARD_QUOTIENT: u64 = 512; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WHISTLEBLOWER_REWARD_QUOTIENT should go below TARGET_COMMITTEE_SIZE
ab3448d to
e76b4f3
Compare
| let whistleblower_index = whistleblower_index.unwrap_or(proposer_index); | ||
|
|
||
| let whistleblower_reward = validator.effective_balance / WHISTLEBLOWER_REWARD_QUOTIENT; | ||
| let proposer_reward = (whistleblower_reward * PROPOSER_WEIGHT) / WEIGHT_DENOMINATOR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let proposer_reward = (whistleblower_reward * PROPOSER_WEIGHT) / WEIGHT_DENOMINATOR; | |
| let proposer_reward = whistleblower_reward * PROPOSER_WEIGHT / WEIGHT_DENOMINATOR; |
these brackets aren't needed due to order of operations
| // Mutably borrow the slashed validator | ||
| let mut binding = self.clone(); | ||
| let validator = binding | ||
| .validators | ||
| .get_mut(slashed_index as usize) | ||
| .ok_or_else(|| anyhow::anyhow!("Validator at index {} not found", slashed_index))?; | ||
|
|
||
| validator.slashed = true; | ||
| validator.withdrawable_epoch = std::cmp::max( | ||
| validator.withdrawable_epoch, | ||
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | ||
| ); | ||
|
|
||
| // Add slashed effective balance to the slashings vector | ||
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | ||
| validator.effective_balance; | ||
|
|
||
| // Decrease validator balance | ||
| self.clone().decrease_balance( | ||
| slashed_index, | ||
| validator.effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Mutably borrow the slashed validator | |
| let mut binding = self.clone(); | |
| let validator = binding | |
| .validators | |
| .get_mut(slashed_index as usize) | |
| .ok_or_else(|| anyhow::anyhow!("Validator at index {} not found", slashed_index))?; | |
| validator.slashed = true; | |
| validator.withdrawable_epoch = std::cmp::max( | |
| validator.withdrawable_epoch, | |
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | |
| ); | |
| // Add slashed effective balance to the slashings vector | |
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | |
| validator.effective_balance; | |
| // Decrease validator balance | |
| self.clone().decrease_balance( | |
| slashed_index, | |
| validator.effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | |
| ); | |
| let validator_effective_balance = if let Some(validator) = self.validators | |
| .get_mut(slashed_index as usize) { | |
| validator.slashed = true; | |
| validator.withdrawable_epoch = std::cmp::max( | |
| validator.withdrawable_epoch, | |
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | |
| ); | |
| validator.effective_balance | |
| } else { | |
| bail!("Validator at index {slashed_index} not found") | |
| }; | |
| // Add slashed effective balance to the slashings vector | |
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | |
| validator_effective_balance; | |
| // Decrease validator balance | |
| self.decrease_balance( | |
| slashed_index, | |
| validator_effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | |
| ); |
You shouldn't be doing clones like this, we aren't using pointers so this code wouldn't work, the cloned object would be different then self. You would be modifying the clone, not self.
e76b4f3 to
f1b7ae5
Compare
| let validator_effective_balance = | ||
| if let Some(validator) = self.validators.get_mut(slashed_index as usize) { | ||
| validator.slashed = true; | ||
| validator.withdrawable_epoch = std::cmp::max( | ||
| validator.withdrawable_epoch, | ||
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | ||
| ); | ||
| validator.effective_balance | ||
| } else { | ||
| bail!("Validator at index {slashed_index} not found") | ||
| }; | ||
| // Add slashed effective balance to the slashings vector | ||
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | ||
| validator_effective_balance; | ||
| // Decrease validator balance | ||
| self.decrease_balance( | ||
| slashed_index, | ||
| validator_effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | ||
| ); | ||
|
|
||
| // Apply proposer and whistleblower rewards | ||
| let proposer_index = self.get_beacon_proposer_index()?; | ||
| let whistleblower_index = whistleblower_index.unwrap_or(proposer_index); | ||
|
|
||
| let whistleblower_reward = | ||
| if let Some(validator) = self.validators.get(slashed_index as usize) { | ||
| validator.effective_balance / WHISTLEBLOWER_REWARD_QUOTIENT | ||
| } else { | ||
| bail!("Validator at index {slashed_index} not found") | ||
| }; | ||
| let proposer_reward = whistleblower_reward * PROPOSER_WEIGHT / WEIGHT_DENOMINATOR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let validator_effective_balance = | |
| if let Some(validator) = self.validators.get_mut(slashed_index as usize) { | |
| validator.slashed = true; | |
| validator.withdrawable_epoch = std::cmp::max( | |
| validator.withdrawable_epoch, | |
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | |
| ); | |
| validator.effective_balance | |
| } else { | |
| bail!("Validator at index {slashed_index} not found") | |
| }; | |
| // Add slashed effective balance to the slashings vector | |
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | |
| validator_effective_balance; | |
| // Decrease validator balance | |
| self.decrease_balance( | |
| slashed_index, | |
| validator_effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | |
| ); | |
| // Apply proposer and whistleblower rewards | |
| let proposer_index = self.get_beacon_proposer_index()?; | |
| let whistleblower_index = whistleblower_index.unwrap_or(proposer_index); | |
| let whistleblower_reward = | |
| if let Some(validator) = self.validators.get(slashed_index as usize) { | |
| validator.effective_balance / WHISTLEBLOWER_REWARD_QUOTIENT | |
| } else { | |
| bail!("Validator at index {slashed_index} not found") | |
| }; | |
| let proposer_reward = whistleblower_reward * PROPOSER_WEIGHT / WEIGHT_DENOMINATOR; | |
| let validator_effective_balance = | |
| if let Some(validator) = self.validators.get_mut(slashed_index as usize) { | |
| validator.slashed = true; | |
| validator.withdrawable_epoch = std::cmp::max( | |
| validator.withdrawable_epoch, | |
| epoch + EPOCHS_PER_SLASHINGS_VECTOR, | |
| ); | |
| validator.effective_balance | |
| } else { | |
| bail!("Validator at index {slashed_index} not found") | |
| }; | |
| // Add slashed effective balance to the slashings vector | |
| self.slashings[(epoch % EPOCHS_PER_SLASHINGS_VECTOR) as usize] += | |
| validator_effective_balance; | |
| // Decrease validator balance | |
| self.decrease_balance( | |
| slashed_index, | |
| validator_effective_balance / MIN_SLASHING_PENALTY_QUOTIENT, | |
| ); | |
| // Apply proposer and whistleblower rewards | |
| let proposer_index = self.get_beacon_proposer_index()?; | |
| let whistleblower_index = whistleblower_index.unwrap_or(proposer_index); | |
| let whistleblower_reward = validator_effective_balance / WHISTLEBLOWER_REWARD_QUOTIENT; | |
| let proposer_reward = whistleblower_reward * PROPOSER_WEIGHT / WEIGHT_DENOMINATOR; |
the effective balance doesn't change in this function, so we don't need to call self.validators.get() again
f1b7ae5 to
b7f44b6
Compare
KolbyML
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good
Added
BeaconStatemutators and functions