9999 - [ Deposit requests] ( #deposit-requests )
100100 - [ New ` process_deposit_request ` ] ( #new-process_deposit_request )
101101 - [ Execution layer consolidation requests] ( #execution-layer-consolidation-requests )
102+ - [ New ` is_valid_switch_to_compounding_request ` ] ( #new-is_valid_switch_to_compounding_request )
102103 - [ New ` process_consolidation_request ` ] ( #new-process_consolidation_request )
103104- [ Testing] ( #testing )
104105
@@ -627,9 +628,8 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
627628``` python
628629def switch_to_compounding_validator (state : BeaconState, index : ValidatorIndex) -> None :
629630 validator = state.validators[index]
630- if has_eth1_withdrawal_credential(validator):
631- validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1 :]
632- queue_excess_active_balance(state, index)
631+ validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1 :]
632+ queue_excess_active_balance(state, index)
633633```
634634
635635#### New ` queue_excess_active_balance `
@@ -858,9 +858,6 @@ def process_pending_consolidations(state: BeaconState) -> None:
858858 if source_validator.withdrawable_epoch > next_epoch:
859859 break
860860
861- # Churn any target excess active balance of target and raise its max
862- switch_to_compounding_validator(state, pending_consolidation.target_index)
863-
864861 # Calculate the consolidated balance
865862 max_effective_balance = get_max_effective_balance(source_validator)
866863 source_effective_balance = min (state.balances[pending_consolidation.source_index], max_effective_balance)
@@ -1217,14 +1214,6 @@ def apply_deposit(state: BeaconState,
12171214 state.pending_balance_deposits.append(
12181215 PendingBalanceDeposit(index = index, amount = amount)
12191216 ) # [Modified in Electra:EIP7251]
1220- # Check if valid deposit switch to compounding credentials
1221- if (
1222- is_compounding_withdrawal_credential(withdrawal_credentials)
1223- and has_eth1_withdrawal_credential(state.validators[index])
1224- and is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature)
1225- ):
1226- switch_to_compounding_validator(state, index)
1227-
12281217```
12291218
12301219###### New ` is_valid_deposit_signature `
@@ -1396,13 +1385,62 @@ def process_deposit_request(state: BeaconState, deposit_request: DepositRequest)
13961385
13971386##### Execution layer consolidation requests
13981387
1388+ ###### New ` is_valid_switch_to_compounding_request `
1389+
1390+ ``` python
1391+ def is_valid_switch_to_compounding_request (
1392+ state : BeaconState,
1393+ consolidation_request : ConsolidationRequest
1394+ ) -> bool :
1395+ # Switch to compounding requires source and target be equal
1396+ if consolidation_request.source_pubkey != consolidation_request.target_pubkey:
1397+ return False
1398+
1399+ # Verify pubkey exists
1400+ source_pubkey = consolidation_request.source_pubkey
1401+ validator_pubkeys = [v.pubkey for v in state.validators]
1402+ if source_pubkey not in validator_pubkeys:
1403+ return False
1404+
1405+ source_validator = state.validators[ValidatorIndex(validator_pubkeys.index(source_pubkey))]
1406+
1407+ # Verify request has been authorized
1408+ if source_validator.withdrawal_credentials[12 :] != consolidation_request.source_address:
1409+ return False
1410+
1411+ # Verify source withdrawal credentials
1412+ if not has_eth1_withdrawal_credential(source_validator):
1413+ return False
1414+
1415+ # Verify the source is active
1416+ current_epoch = get_current_epoch(state)
1417+ if not is_active_validator(source_validator, current_epoch):
1418+ return False
1419+
1420+ # Verify exit for source has not been initiated
1421+ if source_validator.exit_epoch != FAR_FUTURE_EPOCH :
1422+ return False
1423+
1424+ return True
1425+ ```
1426+
13991427###### New ` process_consolidation_request `
14001428
14011429``` python
14021430def process_consolidation_request (
14031431 state : BeaconState,
14041432 consolidation_request : ConsolidationRequest
14051433) -> None :
1434+ if is_valid_switch_to_compounding_request(state, consolidation_request):
1435+ validator_pubkeys = [v.pubkey for v in state.validators]
1436+ request_source_pubkey = consolidation_request.source_pubkey
1437+ source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey))
1438+ switch_to_compounding_validator(state, source_index)
1439+ return
1440+
1441+ # Verify that source != target, so a consolidation cannot be used as an exit.
1442+ if consolidation_request.source_pubkey == consolidation_request.target_pubkey:
1443+ return
14061444 # If the pending consolidations queue is full, consolidation requests are ignored
14071445 if len (state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT :
14081446 return
@@ -1423,10 +1461,6 @@ def process_consolidation_request(
14231461 source_validator = state.validators[source_index]
14241462 target_validator = state.validators[target_index]
14251463
1426- # Verify that source != target, so a consolidation cannot be used as an exit.
1427- if source_index == target_index:
1428- return
1429-
14301464 # Verify source withdrawal credentials
14311465 has_correct_credential = has_execution_withdrawal_credential(source_validator)
14321466 is_correct_source_address = (
@@ -1462,6 +1496,10 @@ def process_consolidation_request(
14621496 source_index = source_index,
14631497 target_index = target_index
14641498 ))
1499+
1500+ # Churn any target excess active balance of target and raise its max
1501+ if has_eth1_withdrawal_credential(target_validator):
1502+ switch_to_compounding_validator(state, target_index)
14651503```
14661504
14671505## Testing
0 commit comments