# [DRAFT] Increase `MaxEB` design considerations <!-- *by [mike neuder](https://twitter.com/mikeneuder) <DATE>* *tl;dr; Evaluate the impact of ePBS on reorg probabilities.* --> <!-- *Many thanks to [Caspar](https://twitter.com/casparschwa), [Chris](https://twitter.com/metachris), [Terence](https://twitter.com/terencechain), [Dan Marzec](https://twitter.com/_danielmarzec), [Anders](https://twitter.com/weboftrees), [Tim](https://twitter.com/timbeiko), [Danny](https://twitter.com/dannyryan), [Jim](https://twitter.com/jgm), and [Rajiv](https://twitter.com/rajivpoc) for comments on draft versions of this document.* --> <!-- --- --> *Purpose – Outline the status of the `MaxEB` [proposal](https://ethresear.ch/t/increase-the-max-effective-balance-a-modest-proposal/15801).* ### Accompanying artifacts - [proposal](https://ethresear.ch/t/increase-the-max-effective-balance-a-modest-proposal/15801) - [min diff pr](https://github.com/michaelneuder/consensus-specs/pull/3/files) - [security considerations doc](https://notes.ethereum.org/@fradamt/meb-increase-security) - [full pyspec pr](https://github.com/michaelneuder/consensus-specs/pull/4/files#diff-4acdddb708abdca02e1e5354345448359a631a949b28dbba14e52b47d8034d77) - [eip pr](https://github.com/ethereum/EIPs/pull/7251) ### Premises 1. Top-ups beyond 32 ETH **MUST NOT** be burned. 3. Increasing the `MaxEB` **MUST** include a partial withdrawals mechanism. ### Features 1. **EL triggered partial withdrawals.** (as long as the balance remains >32 ETH). E.g., a 45 ETH validator should be able to withdrawal up to 13 ETH triggered through the EL. 2. **`0x02` withdrawal credential signals compounding.** These validators will be excluded from the partial withdrawals sweep. 3. **Limiting the penalty of proposer equivocations.** Proposer equivocations should not be proportional to the weight of the proposer, even if attesting equivocations are. 5. **Allow topups past 32 ETH.** These need to be rate limited. 6. (Optional) **Changes to validator behavior being be opt-in.** I.e., validators who don't change anything still have the 32 ETH partial withdrawal sweep. 7. (Optional) **Remove validator sweep all together.** This simplifies UX, but is much more invasive. 12. (Optional) **Rethink the ejection balance.** Can we make it less of a penalty to lose your keys? 9. (Optional) **Allow validators to consolidate without exiting.** Combine validator indices without exiting. This is a massive UX benefit. 10. (Optional) **Allow validators to change to compounding credentials without exiting.** If validators still need to exit, this only turns `N` operations into `N-1` operations, so maybe it is lower priority and the real decision is around (8). 11. ~~(Optional) **Custom ceilings.** Validators can set their ceiling to a custom value based on the 11 empty bytes of the withdrawal credential.~~ ### Deposits design The new deposit flow is as follows. <img src="https://storage.googleapis.com/ethereum-hackmd/upload_a6df617c6f3b408c0503065ac2bdf1b6.png" width=100%> 1. The deposit transaction is included in the `BeaconBlock`. 2. In `process_block` the deposit is added to the pending deposits queue in the state. 3. In `process_epoch` the pending deposit queue processes as many deposits as possible that fit within the churn limit. ### Withdrawals design We can do something similar for the withdrawals flow. <img src="https://storage.googleapis.com/ethereum-hackmd/upload_6f768f1f7dac186d560fa57c55def97c.png" width=100%> 1. EL withdrawals, voluntary exits, and slashings are included in an `ExecutionPayload`. 2. In `process_block`, the withdrawals gets added to the `state.pending_balance_withdrawals` list. 3. In `process_epoch`, the weight-based rate limiting occurs. Once it makes it through the queue, the withdrawal is routed to either the `voluntary` or `slashing` withdrawals queue. 4. In `get_expected_withdrawals`, the pending withdrawals that have an eligible withdrawable epoch are added to a new `ExecutionPayload` in the form of new `Withdrawals` (this is where the actual transfer will take place). The balance is decreased here. Extra notes - If at any point in the flow, a slashing occurs, any withdrawals or exits are removed from `state.pending_balance_withdrawals` and `state.eligible_balance_withdrawals`. A new call to `initiate_validator_exit` is issued after. - The correlated slashing penalty is still processed after half of the exit waiting period. ### Withdrawal edge cases Since withdrawals are inserted and processed in separated stages, there are some edge cases to make sure we cover in the spec. 1. Multiple exits (one from EL one from CL). 2. Overdrawn (larger withdrawal than balance). 3. Withdrawal below 32 ETH. 4. Slashing at different phases of the withdrawal. ### Slashing considerations Current slashing design <img src="https://storage.googleapis.com/ethereum-hackmd/upload_f22e486080ccf0d8509919060e206007.png" width=100%> We use the slashing event as an opportunity to cancel all pending withdrawals for the validator except if they exited, in which case we update their exit and withdrawal epochs. <!-- ```diff def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: """ Initiate the exit of the validator with index ``index``. """ # Return if validator already initiated exit validator = state.validators[index] if validator.exit_epoch != FAR_FUTURE_EPOCH: return + state.pending_balance_withdrawals.append(PendingBalanceWithdrawal(index, validator.balance, True)) - # Compute exit queue epoch - exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH] - exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))]) - exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch]) - if exit_queue_churn >= get_validator_churn_limit(state): - exit_queue_epoch += Epoch(1) - # Set validator exit epoch and withdrawable epoch - validator.exit_epoch = exit_queue_epoch - validator.withdrawable_epoch = Epoch(validator.exit_epoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY) ``` --> ### EL-partials implementation options 1. Include partial withdrawal functionality in [7002](https://github.com/ethereum/EIPs/pull/7002). Consume said functionality in a dependent MaxEB EIP. - *Pros* - Keeps MaxEB EIP contained to just CL layer. - Keeps MaxEB EIP tightly scoped. - *Cons* - Requires changes to 7002 that are not immediately used (no need for partial withdrawals when there is a sweep). 2. Bundle EL-triggered partial withdraws into the MaxEB change. - *Pros* - MaxEB EIP contains all the features it needs. - No changes to 7002 needed. - *Cons* - Larger scope for MaxEB EIP. - MaxEB contains cross layer EL->CL logic (more complex). *I suggest option 1.* ### Expected flows *Consolidation of `n` validators without in-protocol combining feature.* 1. Exit `n-1` of the validators. 2. Update the `nth` validator to use compounding credentials. 3. Top up the `nth` validator with all the withdrawn ETH from the other validators. 4. Use EL triggered partial withdrawals when you want to withdraw some ETH without full exiting. *Requires waiting through the activation queue for `N-1 * 32 ETH`.* --- *Consolidation of `n` validators wit in-protocol combining feature.* 1. Merge each of the `n-1` validators into a specific validator. *No activation queue waiting.*