# Dev Update #9 Hello, Since my [last update](https://hackmd.io/@kevinbogner/dev-update-8), I opened a [draft PR](https://github.com/sigp/lighthouse/pull/3790) for the `sync_committee_rewards`, which is still our primary focus. We all realized that the implementation is *more complex than initially anticipated*. Today, I will break down the challenges we are facing in a *non-technical way*. Explaining our obstacles is a good exercise for me to make sure I understand the concept and is also helpful for people not involved in the topic to understand it better. We mainly discovered the following issues that need to be solved: - [using the correct *state*](#State), - [selecting the right *validators*](#Validators), and - [handling *edge-cases*](#Edge-cases). Next, I want to dig deeper into each of these obstacles. ## State To calculate the rewards accurately, we want to select the proper *state*. The state of Ethereum is an extensive data set containing accounts and balances and a machine state. EVM specifies a ruleset that defines that the state gets changed from block to block.[^1] *Technically* for the calculation, we should use the state from *before* the block is applied, so the *pre-state*. However, the `compute_sync_aggregate_rewards()` function that we use for calculation only changes on the epoch boundary (when `slot % 32 == 0`). So we will get the *same result* for using *pre-block* and *post-block states*. Therefore we will use the post-state because the implementation is more straightforward. This concept took us some time and explanation from sproul to fully understand. ## Validators Another challenge is getting the validators (`validator_index`) that participated in the sync committee. Their job as a validator is to sign every beacon chain header.[^2] That's why we need to check if the validator *voted correctly* by getting the `participation_bit`. If this is the case (`participation_bit == true`), the validator is eligible to get `sync_committee_rewards`; else (`participation_bit == false`), they could get penalized. ## Edge-cases There are also some edge cases that require special treatment. If a validator gets penalized while already having a balance of 0, the `decrease_balance()` function *shouldn't result in a negative validator balance*. Additionally, validators can be in a sync committee multiple times while receiving different rewards and penalties. Sproul suggests the following algorithm to cover both edge cases: ```rust let mut balances = committee_indices.iter().map(|i| (i, state.balances[i])).collect::<HashMap<usize, u64>>(); let mut total_proposer_rewards = 0; // 1. Apply rewards while keeping track of balance updates exactly as the spec does. for (validator_index, participant_bit) in committee_indices.zip(sync_aggregate.sync_committee_bits) { let participant_balance = balances.get_mut(validator_index); if participant_bit { // Increase participant balance *participant_balance += participant_reward; // Increase proposer balance *balances.get_mut(proposer_index) += proposer_reward_per_bit; total_proposer_rewards += proposer_rewards_per_bit; } else { // Decrease participant balance *participant_balance = participant_balance.saturating_sub(participant_reward); } } // Work out the total balance diff for each validator. let rewards = balances.iter().map(|i, new_balance| { let reward = if i != proposer_index { new_balance as i64 - state.balances[i] as i64 } else { new_balance as i64 - states.balances[i] as i64 - total_proposer_rewards }; ValidatorReward { validator_index: i, reward } }).collect(); ``` ## Next I'm confident we will cover these obstacles until my next development update. However, until then, some work needs to be done. [^1]: [Ethereum Virtual Machine (ethereum.org)](https://ethereum.org/en/developers/docs/evm/#:~:text=Ethereum's%20state%20is%20a%20large,are%20defined%20by%20the%20EVM.) [^2]: [Modelling the Impact of Altair (pintail)](https://pintail.xyz/posts/modelling-the-impact-of-altair/#sync-committees)