Skip to content

Commit

Permalink
Merge pull request #4 from ethDreamer/eip-7251
Browse files Browse the repository at this point in the history
Address Comments and Cleanup Spec
  • Loading branch information
dapplion authored Mar 20, 2024
2 parents fc65a6f + f6359f9 commit 7c9fc19
Showing 1 changed file with 135 additions and 75 deletions.
210 changes: 135 additions & 75 deletions specs/_features/eip7251/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
- [New `PendingConsolidation`](#new-pendingconsolidation)
- [Extended Containers](#extended-containers)
- [`BeaconState`](#beaconstate)
- [`BeaconBlockBody`](#beaconblockbody)
- [`BeaconBlockBody`](#beaconblockbody)
- [Helpers](#helpers)
- [Predicates](#predicates)
- [Updated `is_eligible_for_activation_queue`](#updated-is_eligible_for_activation_queue)
Expand All @@ -54,6 +54,8 @@
- [New `process_pending_consolidations`](#new-process_pending_consolidations)
- [Updated `process_effective_balance_updates`](#updated-process_effective_balance_updates)
- [Block processing](#block-processing)
- [Updated `get_expected_withdrawals`](#updated-get_expected_withdrawals)
- [Updated `process_withdrawals`](#updated-process_withdrawals)
- [Operations](#operations)
- [Updated `process_operations`](#updated-process_operations)
- [Deposits](#deposits)
Expand All @@ -62,7 +64,6 @@
- [Updated `get_validator_from_deposit`](#updated-get_validator_from_deposit)
- [Withdrawals](#withdrawals)
- [New `process_execution_layer_withdraw_request`](#new-process_execution_layer_withdraw_request)
- [Updated `get_expected_withdrawals`](#updated-get_expected_withdrawals)
- [Consolidations](#consolidations)
- [New `process_consolidation`](#new-process_consolidation)

Expand Down Expand Up @@ -117,11 +118,11 @@ The following values are (non-configurable) constants used throughout the specif

### State list lengths

| Name | Value | Unit | Duration |
| - | - | :-: | :-: |
| `PENDING_BALANCE_DEPOSITS_LIMIT` | `uint64(2**27)` (= 134,217,728) | pending balance deposits | |
| `PENDING_PARTIAL_WITHDRAWALS_LIMIT` | `uint64(2**27)` (= 134,217,728) | pending partial withdrawals | |
| `PENDING_CONSOLIDATIONS_LIMIT` | `uint64(2**18)` (= 262,144) | pending consolidations | |
| Name | Value | Unit |
| - | - | :-: |
| `PENDING_BALANCE_DEPOSITS_LIMIT` | `uint64(2**27)` (= 134,217,728) | pending balance deposits |
| `PENDING_PARTIAL_WITHDRAWALS_LIMIT` | `uint64(2**27)` (= 134,217,728) | pending partial withdrawals |
| `PENDING_CONSOLIDATIONS_LIMIT` | `uint64(2**18)` (= 262,144) | pending consolidations |


## Configuration
Expand Down Expand Up @@ -244,7 +245,7 @@ class BeaconState(Container):
pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] # [New in EIP-7251]
```

### `BeaconBlockBody`
#### `BeaconBlockBody`

```python
class BeaconBlockBody(Container):
Expand Down Expand Up @@ -324,7 +325,7 @@ def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) ->
Check if ``validator`` is partially withdrawable.
"""
return (
has_execution_withdrawal_credential(validator)
has_execution_withdrawal_credential(validator) # [Modified in EIP7251]
and get_validator_excess_balance(validator, balance) > 0
)
```
Expand Down Expand Up @@ -476,6 +477,15 @@ def slash_validator(state: BeaconState,
state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
slashing_penalty = validator.effective_balance // MIN_SLASHING_PENALTY_QUOTIENT_EIP7251 # [Modified in EIP7251]
decrease_balance(state, slashed_index, slashing_penalty)

# Apply proposer and whistleblower rewards
proposer_index = get_beacon_proposer_index(state)
if whistleblower_index is None:
whistleblower_index = proposer_index
whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
proposer_reward = Gwei(whistleblower_reward * PROPOSER_WEIGHT // WEIGHT_DENOMINATOR)
increase_balance(state, proposer_index, proposer_reward)
increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
```

## Beacon chain state transition function
Expand All @@ -488,12 +498,12 @@ def process_epoch(state: BeaconState) -> None:
process_justification_and_finalization(state)
process_inactivity_updates(state)
process_rewards_and_penalties(state)
process_registry_updates(state)
process_registry_updates(state) # [Modified in EIP7251]
process_slashings(state)
process_eth1_data_reset(state)
process_pending_balance_deposits(state) # New in EIP7251
process_pending_consolidations(state) # New in EIP7251
process_effective_balance_updates(state)
process_effective_balance_updates(state) # [Modified in EIP7251]
process_slashings_reset(state)
process_randao_mixes_reset(state)
```
Expand Down Expand Up @@ -523,17 +533,23 @@ def process_registry_updates(state: BeaconState) -> None:

```python
def process_pending_balance_deposits(state: BeaconState) -> None:
state.deposit_balance_to_consume += get_activation_exit_churn_limit(state)
next_pending_deposit_index = 0
for pending_balance_deposit in state.pending_balance_deposits:
if state.deposit_balance_to_consume < pending_balance_deposit.amount:
available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit(state)
processed_amount = 0
next_deposit_index = 0

for deposit in state.pending_balance_deposits:
if processed_amount + deposit.amount > available_for_processing:
break
increase_balance(state, deposit.index, deposit.amount)
processed_amount += deposit.amount
next_deposit_index += 1

state.deposit_balance_to_consume -= pending_balance_deposit.amount
increase_balance(state, pending_balance_deposit.index, pending_balance_deposit.amount)
next_pending_deposit_index += 1
state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:]

state.pending_balance_deposits = state.pending_balance_deposits[next_pending_deposit_index:]
if len(state.pending_balance_deposits) == 0:
state.deposit_balance_to_consume = 0
else:
state.deposit_balance_to_consume = available_for_processing - processed_amount
```

#### New `process_pending_consolidations`
Expand Down Expand Up @@ -582,6 +598,104 @@ def process_effective_balance_updates(state: BeaconState) -> None:

### Block processing

```python
def process_block(state: BeaconState, block: BeaconBlock) -> None:
process_block_header(state, block)
process_withdrawals(state, block.body.execution_payload) # [Modified in EIP7251]
process_execution_payload(state, block.body, EXECUTION_ENGINE)
process_randao(state, block.body)
process_eth1_data(state, block.body)
process_operations(state, block.body) # [Modified in EIP7251]
process_sync_aggregate(state, block.body.sync_aggregate)
```

##### Updated `get_expected_withdrawals`

```python
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
epoch = get_current_epoch(state)
withdrawal_index = state.next_withdrawal_index
validator_index = state.next_withdrawal_validator_index
withdrawals: List[Withdrawal] = []

# [New in EIP7251] Consume pending partial withdrawals
for withdrawal in state.pending_partial_withdrawals:
if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD // 2:
break

validator = state.validators[withdrawal.index]
if validator.exit_epoch == FAR_FUTURE_EPOCH and state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE:
withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount)
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=withdrawal.index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=withdrawable_balance,
))
withdrawal_index += WithdrawalIndex(1)

partial_withdrawals_len = len(withdrawals)
# END: Consume pending partial withdrawals

# Sweep for remaining.
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
for _ in range(bound):
validator = state.validators[validator_index]
balance = state.balances[validator_index]
if is_fully_withdrawable_validator(validator, balance, epoch):
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=validator_index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=balance,
))
withdrawal_index += WithdrawalIndex(1)
elif is_partially_withdrawable_validator(validator, balance):
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=validator_index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=get_validator_excess_balance(validator, balance), # [Modified in EIP7251]
))
withdrawal_index += WithdrawalIndex(1)
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
break
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
return withdrawals, partial_withdrawals_len
```

##### Updated `process_withdrawals`

```python
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
expected_withdrawals, partial_withdrawals_len = get_expected_withdrawals(state) # [Modified in EIP7251]

assert len(payload.withdrawals) == len(expected_withdrawals)

for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals):
assert withdrawal == expected_withdrawal
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)

# [New in EIP7251] update pending partial withdrawals
state.pending_partial_withdrawals = state.pending_partial_withdrawals[partial_withdrawals_len:]

# Update the next withdrawal index if this block contained withdrawals
if len(expected_withdrawals) != 0:
latest_withdrawal = expected_withdrawals[-1]
state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)

# Update the next validator index to start the next withdrawal sweep
if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
# Next sweep starts after the latest withdrawal's validator index
next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators))
state.next_withdrawal_validator_index = next_validator_index
else:
# Advance sweep by the max length of the sweep if there was not a full set of withdrawals
next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
next_validator_index = ValidatorIndex(next_index % len(state.validators))
state.next_withdrawal_validator_index = next_validator_index
```

#### Operations

##### Updated `process_operations`
Expand All @@ -598,9 +712,9 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
for_ops(body.proposer_slashings, process_proposer_slashing)
for_ops(body.attester_slashings, process_attester_slashing)
for_ops(body.attestations, process_attestation)
for_ops(body.deposits, process_deposit)
for_ops(body.deposits, process_deposit) # [Modified in EIP7251]
for_ops(body.voluntary_exits, process_voluntary_exit)
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # New in EIP7251
for_ops(body.consolidations, process_consolidation) # New in EIP7251
```
Expand Down Expand Up @@ -721,60 +835,6 @@ def process_execution_layer_withdraw_request(
))
```

###### Updated `get_expected_withdrawals`

```python
def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]:
epoch = get_current_epoch(state)
withdrawal_index = state.next_withdrawal_index
validator_index = state.next_withdrawal_validator_index
withdrawals: List[Withdrawal] = []
consumed = 0
for withdrawal in state.pending_partial_withdrawals:
if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD // 2:
break

validator = state.validators[withdrawal.index]
if validator.exit_epoch == FAR_FUTURE_EPOCH and state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE:
withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount)
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=withdrawal.index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=withdrawable_balance,
))
withdrawal_index += WithdrawalIndex(1)
consumed += 1

state.pending_partial_withdrawals = state.pending_partial_withdrawals[consumed:]

# Sweep for remaining.
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
for _ in range(bound):
validator = state.validators[validator_index]
balance = state.balances[validator_index]
if is_fully_withdrawable_validator(validator, balance, epoch):
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=validator_index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=balance,
))
withdrawal_index += WithdrawalIndex(1)
elif is_partially_withdrawable_validator(validator, balance):
withdrawals.append(Withdrawal(
index=withdrawal_index,
validator_index=validator_index,
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
amount=get_validator_excess_balance(validator, balance),
))
withdrawal_index += WithdrawalIndex(1)
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
break
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
return withdrawals
```

##### Consolidations

###### New `process_consolidation`
Expand Down

0 comments on commit 7c9fc19

Please sign in to comment.