|
61 | 61 | - [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices) |
62 | 62 | - [Beacon state mutators](#beacon-state-mutators) |
63 | 63 | - [Modified `initiate_validator_exit`](#modified-initiate_validator_exit) |
| 64 | + - [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator) |
64 | 65 | - [New `queue_excess_active_balance`](#new-queue_excess_active_balance) |
65 | 66 | - [New `queue_entire_balance_and_reset_validator`](#new-queue_entire_balance_and_reset_validator) |
66 | 67 | - [New `compute_exit_epoch_and_update_churn`](#new-compute_exit_epoch_and_update_churn) |
|
96 | 97 | - [Deposit requests](#deposit-requests) |
97 | 98 | - [New `process_deposit_request`](#new-process_deposit_request) |
98 | 99 | - [Execution layer consolidation requests](#execution-layer-consolidation-requests) |
| 100 | + - [New `is_valid_switch_to_compounding_request`](#new-is_valid_switch_to_compounding_request) |
99 | 101 | - [New `process_consolidation_request`](#new-process_consolidation_request) |
100 | 102 | - [Testing](#testing) |
101 | 103 |
|
@@ -677,6 +679,15 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: |
677 | 679 | validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY) |
678 | 680 | ``` |
679 | 681 |
|
| 682 | +#### New `switch_to_compounding_validator` |
| 683 | + |
| 684 | +```python |
| 685 | +def switch_to_compounding_validator(state: BeaconState, index: ValidatorIndex) -> None: |
| 686 | + validator = state.validators[index] |
| 687 | + validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] |
| 688 | + queue_excess_active_balance(state, index) |
| 689 | +``` |
| 690 | + |
680 | 691 | #### New `queue_excess_active_balance` |
681 | 692 |
|
682 | 693 | ```python |
@@ -1383,13 +1394,62 @@ def process_deposit_request(state: BeaconState, deposit_request: DepositRequest) |
1383 | 1394 |
|
1384 | 1395 | ##### Execution layer consolidation requests |
1385 | 1396 |
|
| 1397 | +###### New `is_valid_switch_to_compounding_request` |
| 1398 | + |
| 1399 | +```python |
| 1400 | +def is_valid_switch_to_compounding_request( |
| 1401 | + state: BeaconState, |
| 1402 | + consolidation_request: ConsolidationRequest |
| 1403 | +) -> bool: |
| 1404 | + # Switch to compounding requires source and target be equal |
| 1405 | + if consolidation_request.source_pubkey != consolidation_request.target_pubkey: |
| 1406 | + return False |
| 1407 | + |
| 1408 | + # Verify pubkey exists |
| 1409 | + source_pubkey = consolidation_request.source_pubkey |
| 1410 | + validator_pubkeys = [v.pubkey for v in state.validators] |
| 1411 | + if source_pubkey not in validator_pubkeys: |
| 1412 | + return False |
| 1413 | + |
| 1414 | + source_validator = state.validators[ValidatorIndex(validator_pubkeys.index(source_pubkey))] |
| 1415 | + |
| 1416 | + # Verify request has been authorized |
| 1417 | + if source_validator.withdrawal_credentials[12:] != consolidation_request.source_address: |
| 1418 | + return False |
| 1419 | + |
| 1420 | + # Verify source withdrawal credentials |
| 1421 | + if not has_eth1_withdrawal_credential(source_validator): |
| 1422 | + return False |
| 1423 | + |
| 1424 | + # Verify the source is active |
| 1425 | + current_epoch = get_current_epoch(state) |
| 1426 | + if not is_active_validator(source_validator, current_epoch): |
| 1427 | + return False |
| 1428 | + |
| 1429 | + # Verify exit for source have not been initiated |
| 1430 | + if source_validator.exit_epoch != FAR_FUTURE_EPOCH: |
| 1431 | + return False |
| 1432 | + |
| 1433 | + return True |
| 1434 | +``` |
| 1435 | + |
1386 | 1436 | ###### New `process_consolidation_request` |
1387 | 1437 |
|
1388 | 1438 | ```python |
1389 | 1439 | def process_consolidation_request( |
1390 | 1440 | state: BeaconState, |
1391 | 1441 | consolidation_request: ConsolidationRequest |
1392 | 1442 | ) -> None: |
| 1443 | + if is_valid_switch_to_compounding_request(state, consolidation_request): |
| 1444 | + validator_pubkeys = [v.pubkey for v in state.validators] |
| 1445 | + request_source_pubkey = consolidation_request.source_pubkey |
| 1446 | + source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey)) |
| 1447 | + switch_to_compounding_validator(state, source_index) |
| 1448 | + return |
| 1449 | + |
| 1450 | + # Verify that source != target, so a consolidation cannot be used as an exit. |
| 1451 | + if consolidation_request.source_pubkey == consolidation_request.target_pubkey: |
| 1452 | + return |
1393 | 1453 | # If the pending consolidations queue is full, consolidation requests are ignored |
1394 | 1454 | if len(state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT: |
1395 | 1455 | return |
@@ -1434,28 +1494,21 @@ def process_consolidation_request( |
1434 | 1494 | if target_validator.exit_epoch != FAR_FUTURE_EPOCH: |
1435 | 1495 | return |
1436 | 1496 |
|
1437 | | - # Churn any target excess active balance of target and raise its max |
1438 | | - if has_eth1_withdrawal_credential(target_validator): |
1439 | | - state.validators[target_index].withdrawal_credentials = ( |
1440 | | - COMPOUNDING_WITHDRAWAL_PREFIX + target_validator.withdrawal_credentials[1:] |
1441 | | - ) |
1442 | | - queue_excess_active_balance(state, target_index) |
1443 | | - |
1444 | | - # Verify that source != target, so a consolidation cannot be used as an exit. |
1445 | | - if source_index == target_index: |
1446 | | - return |
1447 | | - |
1448 | 1497 | # Initiate source validator exit and append pending consolidation |
1449 | | - state.validators[source_index].exit_epoch = compute_consolidation_epoch_and_update_churn( |
| 1498 | + source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn( |
1450 | 1499 | state, source_validator.effective_balance |
1451 | 1500 | ) |
1452 | | - state.validators[source_index].withdrawable_epoch = Epoch( |
1453 | | - state.validators[source_index].exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY |
| 1501 | + source_validator.withdrawable_epoch = Epoch( |
| 1502 | + source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY |
1454 | 1503 | ) |
1455 | 1504 | state.pending_consolidations.append(PendingConsolidation( |
1456 | 1505 | source_index=source_index, |
1457 | 1506 | target_index=target_index |
1458 | 1507 | )) |
| 1508 | + |
| 1509 | + # Churn any target excess active balance of target and raise its max |
| 1510 | + if has_eth1_withdrawal_credential(target_validator): |
| 1511 | + switch_to_compounding_validator(state, target_index) |
1459 | 1512 | ``` |
1460 | 1513 |
|
1461 | 1514 | ## Testing |
|
0 commit comments