diff --git a/specs/_features/epbs/beacon-chain.md b/specs/_features/epbs/beacon-chain.md index 3dcb2d9544..ac500c6209 100644 --- a/specs/_features/epbs/beacon-chain.md +++ b/specs/_features/epbs/beacon-chain.md @@ -277,7 +277,7 @@ class ExecutionPayloadHeader(Container): ``` #### `BeaconState` -*Note*: the beacon state is modified to store a signed latest execution payload header. It is also modified to no longer store the full last execution payload header but rather only the last block hash and the last slot that was full, that is in which there were both consensus and execution blocks included. +*Note*: the beacon state is modified to store a signed latest execution payload header, and to track the last withdrawals honored in the CL. It is also modified to no longer store the full last execution payload header but rather only the last block hash and the last slot that was full, that is in which there were both consensus and execution blocks included. ```python class BeaconState(Container): @@ -328,6 +328,7 @@ class BeaconState(Container): latest_block_hash: Hash32 # [New in ePBS] latest_full_slot: Slot # [New in ePBS] signed_execution_payload_header: SignedExecutionPayloadHeader # [New in ePBS] + last_withdrawals_root: Root # [New in ePBS] ``` ## Helper functions @@ -445,7 +446,7 @@ The post-state corresponding to a pre-state `state` and a signed execution paylo ```python def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) # - # removed process_withdrawals(state, block.body.execution_payload) [Removed in ePBS] + removed process_withdrawals(state) [Modified in ePBS] process_execution_payload_header(state, block) # [Modified in ePBS, removed process_execution_payload] process_randao(state, block.body) process_eth1_data(state, block.body) @@ -453,6 +454,37 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_sync_aggregate(state, block.body.sync_aggregate) ``` +#### Modified `process_withdrawals` +**Note:** This is modified to take only the `state` parameter. The payload is required to honor these withdrawals. + +```python +def process_withdrawals(state: BeaconState) -> None: + ## return early if the parent block was empty + if !is_parent_block_full(state): + return + + withdrawals = get_expected_withdrawals(state) + state.last_withdrawals_root = hash_tree_root(withdrawals) + for withdrawal in withdrawals: + decrease_balance(state, withdrawal.validator_index, withdrawal.amount) + + # Update the next withdrawal index if this block contained withdrawals + if len(withdrawals) != 0: + latest_withdrawal = withdrawals[-1] + state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1) + + # Update the next validator index to start the next withdrawal sweep + if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: + # Next sweep starts after the latest withdrawal's validator index + next_validator_index = ValidatorIndex((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 +``` + #### New `verify_execution_payload_header_signature` ```python @@ -627,8 +659,8 @@ def process_execution_payload(state: BeaconState, signed_envelope: SignedExecuti assert verify_execution_envelope_signature(state, signed_envelope) envelope = signed_envelope.message payload = envelope.payload - # Process withdrawals - process_withdrawals(state, payload) + # Verify the withdrawals root + assert hash_tree_root(payload.withdrawals) == state.last_withdrawals_root # Verify inclusion list proposer proposer_index = envelope.inclusion_list_proposer_index assert proposer_index == state.previous_inclusion_list_proposer diff --git a/specs/_features/epbs/validator.md b/specs/_features/epbs/validator.md index b345b808fc..d01ba93ecb 100644 --- a/specs/_features/epbs/validator.md +++ b/specs/_features/epbs/validator.md @@ -1,3 +1,7 @@ +# ePBS -- Honest Validator + +This document represents the changes and additions to the Honest validator guide included in the ePBS fork. + **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* @@ -30,30 +34,13 @@ -# ePBS -- Honest Validator - -**Notice**: This document is a work-in-progress for researchers and implementers. - -## Introduction - -This document represents the changes to be made in the code of an "honest validator" to implement ePBS. - -## Prerequisites - -This document is an extension of the Deneb -- Honest Validator guide. -All behaviors and definitions defined in this document, and documents it extends, carry over unless explicitly noted or overridden. - -All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of ePBS. are requisite for this document and used throughout. -Please see related Beacon Chain doc before continuing and use them as a reference throughout. - ## Protocols ### `ExecutionEngine` *Note*: `get_execution_inclusion_list` function is added to the `ExecutionEngine` protocol for use as a validator. -The body of this function is implementation dependent. -The Engine API may be used to implement it with an external execution engine. +The body of this function is implementation dependent. The Engine API may be used to implement it with an external execution engine. #### `get_execution_inclusion_list` @@ -269,4 +256,4 @@ PTC validators are selected as the first index from each beacon committee, exclu These validators receive a full beacon attestation reward when they correctly identify the payload reveal status. Specifically, if they vote for "full" and the payload is included, or vote for "empty" and the payload is excluded. Attestations directed at the CL block from these validators are disregarded, eliminating the need for broadcasting. -This does not apply if you are an aggregator. \ No newline at end of file +This does not apply if you are an aggregator.