Merge branch 'dev' into deposit-queue

This commit is contained in:
Mikhail Kalinin 2024-09-18 16:01:11 +04:00
commit 1513492944
17 changed files with 234 additions and 251 deletions

View File

@ -12,6 +12,8 @@ on:
default: dev
type: string
required: true
schedule:
- cron: '0 2 * * *'
jobs:
generate-tests:
@ -22,7 +24,7 @@ jobs:
with:
repository: 'ethereum/consensus-specs'
path: 'consensus-specs'
ref: ${{ inputs.source_ref }}
ref: ${{ inputs.source_ref || 'dev' }}
- name: Checkout consensus-spec-tests repository
uses: actions/checkout@v4
with:

View File

@ -19,3 +19,41 @@ from eth2spec.deneb import {preset_name} as deneb
'CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(86)',
'NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA': 'GeneralizedIndex(87)',
}
@classmethod
def execution_engine_cls(cls) -> str:
return """
class NoopExecutionEngine(ExecutionEngine):
def notify_new_payload(self: ExecutionEngine,
execution_payload: ExecutionPayload,
execution_requests: ExecutionRequests,
parent_beacon_block_root: Root) -> bool:
return True
def notify_forkchoice_updated(self: ExecutionEngine,
head_block_hash: Hash32,
safe_block_hash: Hash32,
finalized_block_hash: Hash32,
payload_attributes: Optional[PayloadAttributes]) -> Optional[PayloadId]:
pass
def get_payload(self: ExecutionEngine, payload_id: PayloadId) -> GetPayloadResponse:
# pylint: disable=unused-argument
raise NotImplementedError("no default block production")
def is_valid_block_hash(self: ExecutionEngine,
execution_payload: ExecutionPayload,
parent_beacon_block_root: Root) -> bool:
return True
def is_valid_versioned_hashes(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool:
return True
def verify_and_notify_new_payload(self: ExecutionEngine,
new_payload_request: NewPayloadRequest) -> bool:
return True
EXECUTION_ENGINE = NoopExecutionEngine()"""

View File

@ -15,8 +15,6 @@
- [BLS12-381 helpers](#bls12-381-helpers)
- [`cell_to_coset_evals`](#cell_to_coset_evals)
- [`coset_evals_to_cell`](#coset_evals_to_cell)
- [Linear combinations](#linear-combinations)
- [`g2_lincomb`](#g2_lincomb)
- [FFTs](#ffts)
- [`_fft_field`](#_fft_field)
- [`fft_field`](#fft_field)
@ -125,28 +123,6 @@ def coset_evals_to_cell(coset_evals: CosetEvals) -> Cell:
return Cell(cell)
```
### Linear combinations
#### `g2_lincomb`
```python
def g2_lincomb(points: Sequence[G2Point], scalars: Sequence[BLSFieldElement]) -> Bytes96:
"""
BLS multiscalar multiplication in G2. This can be naively implemented using double-and-add.
"""
assert len(points) == len(scalars)
if len(points) == 0:
return bls.G2_to_bytes96(bls.Z2())
points_g2 = []
for point in points:
points_g2.append(bls.bytes96_to_G2(point))
result = bls.multi_exp(points_g2, scalars)
return Bytes96(bls.G2_to_bytes96(result))
```
### FFTs
#### `_fft_field`

View File

@ -156,6 +156,7 @@ class SignedExecutionPayloadHeader(Container):
```python
class ExecutionPayloadEnvelope(Container):
payload: ExecutionPayload
execution_requests: ExecutionRequests
builder_index: ValidatorIndex
beacon_block_root: Root
blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
@ -175,7 +176,7 @@ class SignedExecutionPayloadEnvelope(Container):
#### `BeaconBlockBody`
**Note:** The Beacon Block body is modified to contain a `Signed ExecutionPayloadHeader`. The containers `BeaconBlock` and `SignedBeaconBlock` are modified indirectly.
**Note:** The Beacon Block body is modified to contain a `Signed ExecutionPayloadHeader`. The containers `BeaconBlock` and `SignedBeaconBlock` are modified indirectly. The field `execution_requests` is removed from the beacon block body and moved into the signed execution payload envelope.
```python
class BeaconBlockBody(Container):
@ -191,8 +192,9 @@ class BeaconBlockBody(Container):
sync_aggregate: SyncAggregate
# Execution
# Removed execution_payload [Removed in EIP-7732]
# Removed blob_kzg_commitments [Removed in EIP-7732]
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
# Removed blob_kzg_commitments [Removed in EIP-7732]
# Removed execution_requests [Removed in EIP-7732]
# PBS
signed_execution_payload_header: SignedExecutionPayloadHeader # [New in EIP-7732]
payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS] # [New in EIP-7732]
@ -650,11 +652,13 @@ def process_execution_payload(state: BeaconState,
# Verify the execution payload is valid
versioned_hashes = [kzg_commitment_to_versioned_hash(commitment)
for commitment in envelope.blob_kzg_commitments]
requests = envelope.execution_requests
assert execution_engine.verify_and_notify_new_payload(
NewPayloadRequest(
execution_payload=payload,
versioned_hashes=versioned_hashes,
parent_beacon_block_root=state.latest_block_header.parent_root,
execution_requests=requests,
)
)
@ -663,9 +667,9 @@ def process_execution_payload(state: BeaconState,
for operation in operations:
fn(state, operation)
for_ops(payload.deposit_requests, process_deposit_request)
for_ops(payload.withdrawal_requests, process_withdrawal_request)
for_ops(payload.consolidation_requests, process_consolidation_request)
for_ops(requests.deposit_requests, process_deposit_request)
for_ops(requests.withdrawal_requests, process_withdrawal_request)
for_ops(requests.consolidation_requests, process_consolidation_request)
# Cache the execution payload header and proposer
state.latest_block_hash = payload.block_hash

View File

@ -12,7 +12,6 @@
- [Constants](#constants)
- [Misc](#misc)
- [Withdrawal prefixes](#withdrawal-prefixes)
- [Domains](#domains)
- [Preset](#preset)
- [Gwei values](#gwei-values)
- [Rewards and penalties](#rewards-and-penalties)
@ -31,14 +30,13 @@
- [`WithdrawalRequest`](#withdrawalrequest)
- [`ConsolidationRequest`](#consolidationrequest)
- [`PendingConsolidation`](#pendingconsolidation)
- [`ExecutionRequests`](#executionrequests)
- [Modified Containers](#modified-containers)
- [`AttesterSlashing`](#attesterslashing)
- [`BeaconBlockBody`](#beaconblockbody)
- [Extended Containers](#extended-containers)
- [`Attestation`](#attestation)
- [`IndexedAttestation`](#indexedattestation)
- [`BeaconBlockBody`](#beaconblockbody)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
- [`BeaconState`](#beaconstate)
- [Helper functions](#helper-functions)
- [Predicates](#predicates)
@ -72,10 +70,17 @@
- [Epoch processing](#epoch-processing)
- [Modified `process_epoch`](#modified-process_epoch)
- [Modified `process_registry_updates`](#modified-process_registry_updates)
- [Modified `process_slashings`](#modified-process_slashings)
- [New `apply_pending_deposit`](#new-apply_pending_deposit)
- [New `process_pending_deposits`](#new-process_pending_deposits)
- [New `process_pending_consolidations`](#new-process_pending_consolidations)
- [Modified `process_effective_balance_updates`](#modified-process_effective_balance_updates)
- [Execution engine](#execution-engine)
- [Request data](#request-data)
- [Modified `NewPayloadRequest`](#modified-newpayloadrequest)
- [Engine APIs](#engine-apis)
- [Modified `notify_new_payload`](#modified-notify_new_payload)
- [Modified `verify_and_notify_new_payload`](#modified-verify_and_notify_new_payload)
- [Block processing](#block-processing)
- [Withdrawals](#withdrawals)
- [Modified `get_expected_withdrawals`](#modified-get_expected_withdrawals)
@ -130,12 +135,6 @@ The following values are (non-configurable) constants used throughout the specif
| - | - |
| `COMPOUNDING_WITHDRAWAL_PREFIX` | `Bytes1('0x02')` |
### Domains
| Name | Value |
| - | - |
| `DOMAIN_CONSOLIDATION` | `DomainType('0x0B000000')` |
## Preset
### Gwei values
@ -267,6 +266,19 @@ class PendingConsolidation(Container):
target_index: ValidatorIndex
```
#### `ExecutionRequests`
*Note*: This container holds requests from the execution layer that are received in [
`ExecutionPayloadV4`](https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#executionpayloadv4) via
the Engine API. These requests are required for CL state transition (see `BeaconBlockBody`).
```python
class ExecutionRequests(Container):
deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110]
withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7002:EIP7251]
consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP7251]
```
### Modified Containers
#### `AttesterSlashing`
@ -277,6 +289,27 @@ class AttesterSlashing(Container):
attestation_2: IndexedAttestation # [Modified in Electra:EIP7549]
```
#### `BeaconBlockBody`
```python
class BeaconBlockBody(Container):
randao_reveal: BLSSignature
eth1_data: Eth1Data # Eth1 data vote
graffiti: Bytes32 # Arbitrary data
# Operations
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] # [Modified in Electra:EIP7549]
attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] # [Modified in Electra:EIP7549]
deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
sync_aggregate: SyncAggregate
# Execution
execution_payload: ExecutionPayload
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
execution_requests: ExecutionRequests # [New in Electra]
```
### Extended Containers
#### `Attestation`
@ -299,84 +332,6 @@ class IndexedAttestation(Container):
signature: BLSSignature
```
#### `BeaconBlockBody`
```python
class BeaconBlockBody(Container):
randao_reveal: BLSSignature
eth1_data: Eth1Data # Eth1 data vote
graffiti: Bytes32 # Arbitrary data
# Operations
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA] # [Modified in Electra:EIP7549]
attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA] # [Modified in Electra:EIP7549]
deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
sync_aggregate: SyncAggregate
# Execution
execution_payload: ExecutionPayload # [Modified in Electra:EIP6110:EIP7002]
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
```
#### `ExecutionPayload`
```python
class ExecutionPayload(Container):
# Execution block header fields
parent_hash: Hash32
fee_recipient: ExecutionAddress
state_root: Bytes32
receipts_root: Bytes32
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
prev_randao: Bytes32
block_number: uint64
gas_limit: uint64
gas_used: uint64
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
# Extra payload fields
block_hash: Hash32
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
blob_gas_used: uint64
excess_blob_gas: uint64
deposit_requests: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD] # [New in Electra:EIP6110]
# [New in Electra:EIP7002:EIP7251]
withdrawal_requests: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]
# [New in Electra:EIP7251]
consolidation_requests: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]
```
#### `ExecutionPayloadHeader`
```python
class ExecutionPayloadHeader(Container):
# Execution block header fields
parent_hash: Hash32
fee_recipient: ExecutionAddress
state_root: Bytes32
receipts_root: Bytes32
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
prev_randao: Bytes32
block_number: uint64
gas_limit: uint64
gas_used: uint64
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
# Extra payload fields
block_hash: Hash32
transactions_root: Root
withdrawals_root: Root
blob_gas_used: uint64
excess_blob_gas: uint64
deposit_requests_root: Root # [New in Electra:EIP6110]
withdrawal_requests_root: Root # [New in Electra:EIP7002:EIP7251]
consolidation_requests_root: Root # [New in Electra:EIP7251]
```
#### `BeaconState`
```python
@ -831,7 +786,7 @@ def process_epoch(state: BeaconState) -> None:
process_inactivity_updates(state)
process_rewards_and_penalties(state)
process_registry_updates(state) # [Modified in Electra:EIP7251]
process_slashings(state)
process_slashings(state) # [Modified in Electra:EIP7251]
process_eth1_data_reset(state)
process_pending_deposits(state) # [New in Electra:EIP7251]
process_pending_consolidations(state) # [New in Electra:EIP7251]
@ -868,6 +823,28 @@ def process_registry_updates(state: BeaconState) -> None:
validator.activation_epoch = activation_epoch
```
#### Modified `process_slashings`
*Note*: The function `process_slashings` is modified to use a new algorithm to compute correlation penalty.
```python
def process_slashings(state: BeaconState) -> None:
epoch = get_current_epoch(state)
total_balance = get_total_active_balance(state)
adjusted_total_slashing_balance = min(
sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX,
total_balance
)
increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid uint64 overflow
penalty_per_effective_balance_increment = adjusted_total_slashing_balance // (total_balance // increment)
for index, validator in enumerate(state.validators):
if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
effective_balance_increments = validator.effective_balance // increment
# [Modified in Electra:EIP7251]
penalty = penalty_per_effective_balance_increment * effective_balance_increments
decrease_balance(state, ValidatorIndex(index), penalty)
```
#### New `apply_pending_deposit`
```python
@ -1014,6 +991,70 @@ def process_effective_balance_updates(state: BeaconState) -> None:
validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, EFFECTIVE_BALANCE_LIMIT)
```
### Execution engine
#### Request data
##### Modified `NewPayloadRequest`
```python
@dataclass
class NewPayloadRequest(object):
execution_payload: ExecutionPayload
versioned_hashes: Sequence[VersionedHash]
parent_beacon_block_root: Root
execution_requests: ExecutionRequests # [New in Electra]
```
#### Engine APIs
##### Modified `notify_new_payload`
*Note*: The function `notify_new_payload` is modified to include the additional `execution_requests` parameter in Electra.
```python
def notify_new_payload(self: ExecutionEngine,
execution_payload: ExecutionPayload,
execution_requests: ExecutionRequests,
parent_beacon_block_root: Root) -> bool:
"""
Return ``True`` if and only if ``execution_payload`` and ``execution_requests``
are valid with respect to ``self.execution_state``.
"""
...
```
##### Modified `verify_and_notify_new_payload`
*Note*: The function `verify_and_notify_new_payload` is modified to pass the additional parameter `execution_requests`
when calling `notify_new_payload` in Electra.
```python
def verify_and_notify_new_payload(self: ExecutionEngine,
new_payload_request: NewPayloadRequest) -> bool:
"""
Return ``True`` if and only if ``new_payload_request`` is valid with respect to ``self.execution_state``.
"""
execution_payload = new_payload_request.execution_payload
execution_requests = new_payload_request.execution_requests # [New in Electra]
parent_beacon_block_root = new_payload_request.parent_beacon_block_root
if not self.is_valid_block_hash(execution_payload, parent_beacon_block_root):
return False
if not self.is_valid_versioned_hashes(new_payload_request):
return False
# [Modified in Electra]
if not self.notify_new_payload(
execution_payload,
execution_requests,
parent_beacon_block_root):
return False
return True
```
### Block processing
```python
@ -1124,7 +1165,7 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
##### Modified `process_execution_payload`
*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type.
*Note*: The function `process_execution_payload` is modified to pass `execution_requests` into `execution_engine.verify_and_notify_new_payload` (via the updated `NewPayloadRequest`).
```python
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
@ -1143,6 +1184,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi
assert execution_engine.verify_and_notify_new_payload(
NewPayloadRequest(
execution_payload=payload,
execution_requests=body.execution_requests, # [New in Electra]
versioned_hashes=versioned_hashes,
parent_beacon_block_root=state.latest_block_header.parent_root,
)
@ -1166,9 +1208,6 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi
withdrawals_root=hash_tree_root(payload.withdrawals),
blob_gas_used=payload.blob_gas_used,
excess_blob_gas=payload.excess_blob_gas,
deposit_requests_root=hash_tree_root(payload.deposit_requests), # [New in Electra:EIP6110]
withdrawal_requests_root=hash_tree_root(payload.withdrawal_requests), # [New in Electra:EIP7002:EIP7251]
consolidation_requests_root=hash_tree_root(payload.consolidation_requests), # [New in Electra:EIP7251]
)
```
@ -1195,14 +1234,12 @@ 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) # [Modified in Electra:EIP7549]
for_ops(body.deposits, process_deposit) # [Modified in Electra:EIP7251]
for_ops(body.deposits, process_deposit)
for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in Electra:EIP7251]
for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
for_ops(body.execution_payload.deposit_requests, process_deposit_request) # [New in Electra:EIP6110]
# [New in Electra:EIP7002:EIP7251]
for_ops(body.execution_payload.withdrawal_requests, process_withdrawal_request)
# [New in Electra:EIP7251]
for_ops(body.execution_payload.consolidation_requests, process_consolidation_request)
for_ops(body.execution_requests.deposits, process_deposit_request) # [New in Electra:EIP6110]
for_ops(body.execution_requests.withdrawals, process_withdrawal_request) # [New in Electra:EIP7002:EIP7251]
for_ops(body.execution_requests.consolidations, process_consolidation_request) # [New in Electra:EIP7251]
```
##### Attestations
@ -1281,7 +1318,7 @@ def get_validator_from_deposit(pubkey: BLSPubkey, withdrawal_credentials: Bytes3
###### Modified `apply_deposit`
*Note*: The function `process_deposit` is modified to support EIP7251.
*Note*: The function `apply_deposit` is modified to support EIP7251.
```python
def apply_deposit(state: BeaconState,

View File

@ -72,28 +72,7 @@ an irregular state change is made to upgrade to Electra.
```python
def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState:
epoch = deneb.get_current_epoch(pre)
latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=pre.latest_execution_payload_header.parent_hash,
fee_recipient=pre.latest_execution_payload_header.fee_recipient,
state_root=pre.latest_execution_payload_header.state_root,
receipts_root=pre.latest_execution_payload_header.receipts_root,
logs_bloom=pre.latest_execution_payload_header.logs_bloom,
prev_randao=pre.latest_execution_payload_header.prev_randao,
block_number=pre.latest_execution_payload_header.block_number,
gas_limit=pre.latest_execution_payload_header.gas_limit,
gas_used=pre.latest_execution_payload_header.gas_used,
timestamp=pre.latest_execution_payload_header.timestamp,
extra_data=pre.latest_execution_payload_header.extra_data,
base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas,
block_hash=pre.latest_execution_payload_header.block_hash,
transactions_root=pre.latest_execution_payload_header.transactions_root,
withdrawals_root=pre.latest_execution_payload_header.withdrawals_root,
blob_gas_used=pre.latest_execution_payload_header.blob_gas_used,
excess_blob_gas=pre.latest_execution_payload_header.excess_blob_gas,
deposit_requests_root=Root(), # [New in Electra:EIP6110]
withdrawal_requests_root=Root(), # [New in Electra:EIP7002]
consolidation_requests_root=Root(), # [New in Electra:EIP7251]
)
latest_execution_payload_header = pre.latest_execution_payload_header
exit_epochs = [v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH]
if not exit_epochs:

View File

@ -39,28 +39,7 @@ A Electra `LightClientStore` can still process earlier light client data. In ord
def upgrade_lc_header_to_electra(pre: deneb.LightClientHeader) -> LightClientHeader:
return LightClientHeader(
beacon=pre.beacon,
execution=ExecutionPayloadHeader(
parent_hash=pre.execution.parent_hash,
fee_recipient=pre.execution.fee_recipient,
state_root=pre.execution.state_root,
receipts_root=pre.execution.receipts_root,
logs_bloom=pre.execution.logs_bloom,
prev_randao=pre.execution.prev_randao,
block_number=pre.execution.block_number,
gas_limit=pre.execution.gas_limit,
gas_used=pre.execution.gas_used,
timestamp=pre.execution.timestamp,
extra_data=pre.execution.extra_data,
base_fee_per_gas=pre.execution.base_fee_per_gas,
block_hash=pre.execution.block_hash,
transactions_root=pre.execution.transactions_root,
withdrawals_root=pre.execution.withdrawals_root,
blob_gas_used=pre.execution.blob_gas_used,
excess_blob_gas=pre.execution.blob_gas_used,
deposit_requests_root=Root(), # [New in Electra:EIP6110]
withdrawal_requests_root=Root(), # [New in Electra:EIP7002:EIP7251]
consolidation_requests_root=Root(), # [New in Electra:EIP7251]
),
execution=pre.execution,
execution_branch=pre.execution_branch,
)
```

View File

@ -50,12 +50,6 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader:
execution_header.blob_gas_used = payload.blob_gas_used
execution_header.excess_blob_gas = payload.excess_blob_gas
# [New in Electra:EIP6110:EIP7002:EIP7251]
if epoch >= ELECTRA_FORK_EPOCH:
execution_header.deposit_requests_root = hash_tree_root(payload.deposit_requests)
execution_header.withdrawal_requests_root = hash_tree_root(payload.withdrawal_requests)
execution_header.consolidation_requests_root = hash_tree_root(payload.consolidation_requests)
execution_branch = ExecutionBranch(
compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX))
else:

View File

@ -159,15 +159,6 @@ def get_lc_execution_root(header: LightClientHeader) -> Root:
def is_valid_light_client_header(header: LightClientHeader) -> bool:
epoch = compute_epoch_at_slot(header.beacon.slot)
# [New in Electra:EIP6110:EIP7002:EIP7251]
if epoch < ELECTRA_FORK_EPOCH:
if (
header.execution.deposit_requests_root != Root()
or header.execution.withdrawal_requests_root != Root()
or header.execution.consolidation_requests_root != Root()
):
return False
if epoch < DENEB_FORK_EPOCH:
if header.execution.blob_gas_used != uint64(0) or header.execution.excess_blob_gas != uint64(0):
return False

View File

@ -41,7 +41,7 @@ def test_basic_el_withdrawal_request(spec, state):
validator_pubkey=validator_pubkey,
)
block = build_empty_block_for_next_slot(spec, state)
block.body.execution_payload.withdrawal_requests = [withdrawal_request]
block.body.execution_requests.withdrawals = [withdrawal_request]
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
signed_block = state_transition_and_sign_block(spec, state, block)
@ -77,7 +77,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state):
source_address=address,
validator_pubkey=validator_pubkey,
)
block.body.execution_payload.withdrawal_requests = [withdrawal_request]
block.body.execution_requests.withdrawals = [withdrawal_request]
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
signed_block = state_transition_and_sign_block(spec, state, block)
@ -130,7 +130,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state):
validator_pubkey=validator_pubkey,
)
block_2 = build_empty_block_for_next_slot(spec, state)
block_2.body.execution_payload.withdrawal_requests = [withdrawal_request]
block_2.body.execution_requests.withdrawals = [withdrawal_request]
block_2.body.execution_payload.block_hash = compute_el_block_hash(spec, block_2.body.execution_payload, state)
signed_block_2 = state_transition_and_sign_block(spec, state, block_2)
@ -163,7 +163,7 @@ def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state):
)
block = build_empty_block_for_next_slot(spec, state)
block.body.voluntary_exits = signed_voluntary_exits
block.body.execution_payload.withdrawal_requests = [withdrawal_request]
block.body.execution_requests.withdrawals = [withdrawal_request]
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
signed_block = state_transition_and_sign_block(spec, state, block)

View File

@ -62,7 +62,7 @@ def run_deposit_transition_block(spec, state, block, top_up_keys=[], valid=True)
assert len(state.validators) == pre_validators_len + len(block.body.deposits)
# Check that deposit requests are processed
for i, deposit_request in enumerate(block.body.execution_payload.deposit_requests):
for i, deposit_request in enumerate(block.body.execution_requests.deposits):
# The corresponding pending deposit is created
pending_deposit = state.pending_deposits[pre_pending_deposits_len + len(block.body.deposits) + i]
assert pending_deposit.pubkey == deposit_request.pubkey
@ -73,7 +73,7 @@ def run_deposit_transition_block(spec, state, block, top_up_keys=[], valid=True)
# Assert that no unexpected pending deposits were created
assert len(state.pending_deposits) == pre_pending_deposits_len + len(
block.body.deposits) + len(block.body.execution_payload.deposit_requests)
block.body.deposits) + len(block.body.execution_requests.deposits)
def prepare_state_and_block(spec,
@ -133,7 +133,7 @@ def prepare_state_and_block(spec,
# Assign deposits and deposit requests
block.body.deposits = deposits
block.body.execution_payload.deposit_requests = deposit_requests
block.body.execution_requests.deposits = deposit_requests
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
return state, block
@ -151,7 +151,7 @@ def test_deposit_transition__start_index_is_set(spec, state):
yield from run_deposit_transition_block(spec, state, block)
# deposit_requests_start_index must be set to the index of the first request
assert state.deposit_requests_start_index == block.body.execution_payload.deposit_requests[0].index
assert state.deposit_requests_start_index == block.body.execution_requests.deposits[0].index
@with_phases([ELECTRA])
@ -250,7 +250,7 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state):
# Artificially assign deposit's pubkey to a deposit request of the same block
top_up_keys = [block.body.deposits[0].data.pubkey]
block.body.execution_payload.deposit_requests[0].pubkey = top_up_keys[0]
block.body.execution_requests.deposits[0].pubkey = top_up_keys[0]
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
pre_pending_deposits = len(state.pending_deposits)
@ -260,5 +260,5 @@ def test_deposit_transition__deposit_and_top_up_same_block(spec, state):
# Check the top up
assert len(state.pending_deposits) == pre_pending_deposits + 2
assert state.pending_deposits[pre_pending_deposits].amount == block.body.deposits[0].data.amount
amount_from_deposit = block.body.execution_payload.deposit_requests[0].amount
amount_from_deposit = block.body.execution_requests.deposits[0].amount
assert state.pending_deposits[pre_pending_deposits + 1].amount == amount_from_deposit

View File

@ -1,6 +1,7 @@
from eth2spec.test.helpers.execution_payload import build_empty_execution_payload
from eth2spec.test.helpers.execution_payload import build_empty_signed_execution_payload_header
from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732
from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732, \
is_post_electra
from eth2spec.test.helpers.keys import privkeys, whisk_ks_initial, whisk_ks_final
from eth2spec.utils import bls
from eth2spec.utils.bls import only_with_bls
@ -126,6 +127,11 @@ def build_empty_block(spec, state, slot=None, proposer_index=None):
if is_post_bellatrix(spec):
empty_block.body.execution_payload = build_empty_execution_payload(spec, state)
if is_post_electra(spec):
empty_block.body.execution_requests.deposits = []
empty_block.body.execution_requests.withdrawals = []
empty_block.body.execution_requests.consolidations = []
if is_post_whisk(spec):
# Whisk opening proof
#######

View File

@ -38,13 +38,14 @@ def run_fork_test(post_spec, pre_state):
'next_withdrawal_index', 'next_withdrawal_validator_index',
# Deep history valid from Capella onwards
'historical_summaries',
'latest_execution_payload_header'
]
for field in stable_fields:
assert getattr(pre_state, field) == getattr(post_state, field)
# Modified fields
modified_fields = ['fork', 'latest_execution_payload_header']
modified_fields = ['fork']
for field in modified_fields:
assert getattr(pre_state, field) != getattr(post_state, field)

View File

@ -36,8 +36,6 @@ def get_process_calls(spec):
'process_participation_record_updates'
),
'process_sync_committee_updates', # altair
'process_full_withdrawals', # capella
'process_partial_withdrawals', # capella
# TODO: add sharding processing functions when spec stabilizes.
]

View File

@ -7,12 +7,7 @@ from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
from eth2spec.debug.random_value import get_random_bytes_list
from eth2spec.test.helpers.withdrawals import get_expected_withdrawals
from eth2spec.test.helpers.forks import (
is_post_capella,
is_post_deneb,
is_post_electra,
is_post_eip7732,
)
from eth2spec.test.helpers.forks import is_post_capella, is_post_deneb, is_post_eip7732
def get_execution_payload_header(spec, execution_payload):
@ -49,10 +44,6 @@ def get_execution_payload_header(spec, execution_payload):
if is_post_deneb(spec):
payload_header.blob_gas_used = execution_payload.blob_gas_used
payload_header.excess_blob_gas = execution_payload.excess_blob_gas
if is_post_electra(spec):
payload_header.deposit_requests_root = spec.hash_tree_root(execution_payload.deposit_requests)
payload_header.withdrawal_requests_root = spec.hash_tree_root(execution_payload.withdrawal_requests)
payload_header.consolidation_requests_root = spec.hash_tree_root(execution_payload.consolidation_requests)
return payload_header
@ -74,8 +65,7 @@ def compute_el_header_block_hash(spec,
payload_header,
transactions_trie_root,
withdrawals_trie_root=None,
parent_beacon_block_root=None,
requests_trie_root=None):
parent_beacon_block_root=None):
"""
Computes the RLP execution block hash described by an `ExecutionPayloadHeader`.
"""
@ -126,9 +116,6 @@ def compute_el_header_block_hash(spec,
execution_payload_header_rlp.append((big_endian_int, payload_header.excess_blob_gas))
# parent_beacon_root
execution_payload_header_rlp.append((Binary(32, 32), parent_beacon_block_root))
if is_post_electra(spec):
# requests_root
execution_payload_header_rlp.append((Binary(32, 32), requests_trie_root))
sedes = List([schema for schema, _ in execution_payload_header_rlp])
values = [value for _, value in execution_payload_header_rlp]
@ -209,20 +196,12 @@ def compute_el_block_hash(spec, payload, pre_state):
withdrawals_trie_root = None
parent_beacon_block_root = None
requests_trie_root = None
if is_post_capella(spec):
withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals]
withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded)
if is_post_deneb(spec):
parent_beacon_block_root = pre_state.latest_block_header.hash_tree_root()
if is_post_electra(spec):
requests_encoded = []
requests_encoded += [get_deposit_request_rlp_bytes(request) for request in payload.deposit_requests]
requests_encoded += [get_withdrawal_request_rlp_bytes(request) for request in payload.withdrawal_requests]
requests_encoded += [get_consolidation_request_rlp_bytes(request) for request in payload.consolidation_requests]
requests_trie_root = compute_trie_root_from_indexed_data(requests_encoded)
payload_header = get_execution_payload_header(spec, payload)
@ -232,7 +211,6 @@ def compute_el_block_hash(spec, payload, pre_state):
transactions_trie_root,
withdrawals_trie_root,
parent_beacon_block_root,
requests_trie_root,
)
@ -296,10 +274,6 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
if is_post_deneb(spec):
payload.blob_gas_used = 0
payload.excess_blob_gas = 0
if is_post_electra(spec):
payload.deposit_requests = []
payload.withdrawal_requests = []
payload.consolidation_requests = []
payload.block_hash = compute_el_block_hash(spec, payload, state)

View File

@ -66,14 +66,11 @@ def get_sample_genesis_execution_payload_header(spec,
transactions_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
withdrawals_trie_root = None
parent_beacon_block_root = None
requests_trie_root = None
if is_post_capella(spec):
withdrawals_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
if is_post_deneb(spec):
parent_beacon_block_root = bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000")
if is_post_electra(spec):
requests_trie_root = bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
payload_header.block_hash = compute_el_header_block_hash(
spec,
@ -81,7 +78,6 @@ def get_sample_genesis_execution_payload_header(spec,
transactions_trie_root,
withdrawals_trie_root,
parent_beacon_block_root,
requests_trie_root,
)
return payload_header

View File

@ -3,7 +3,11 @@ from eth2spec.test.context import spec_state_test, with_all_phases
from eth2spec.test.helpers.epoch_processing import (
run_epoch_processing_with, run_epoch_processing_to
)
from eth2spec.test.helpers.forks import is_post_altair, is_post_bellatrix
from eth2spec.test.helpers.forks import (
is_post_altair,
is_post_bellatrix,
is_post_electra,
)
from eth2spec.test.helpers.random import randomize_state
from eth2spec.test.helpers.state import has_active_balance_differential
from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators
@ -40,6 +44,18 @@ def get_slashing_multiplier(spec):
return spec.PROPORTIONAL_SLASHING_MULTIPLIER
def _compute_expected_correlation_penalty(spec, effective_balance, total_slashed_balance, total_balance):
if is_post_electra(spec):
return ((get_slashing_multiplier(spec) * total_slashed_balance)
// (total_balance // spec.EFFECTIVE_BALANCE_INCREMENT)
* (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT))
else:
return (effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
* (get_slashing_multiplier(spec) * total_slashed_balance)
// total_balance
* spec.EFFECTIVE_BALANCE_INCREMENT)
def _setup_process_slashings_test(spec, state, not_slashable_set=set()):
# Slashed count to ensure that enough validators are slashed to induce maximum penalties
slashed_count = min(
@ -99,7 +115,8 @@ def test_minimal_penalty(spec, state):
#
# Just the bare minimum for this one validator
state.balances[0] = state.validators[0].effective_balance = spec.config.EJECTION_BALANCE
state.balances[0] = state.validators[0].effective_balance = (
spec.config.EJECTION_BALANCE + spec.EFFECTIVE_BALANCE_INCREMENT)
# All the other validators get the maximum.
for i in range(1, len(state.validators)):
state.validators[i].effective_balance = state.balances[i] = spec.MAX_EFFECTIVE_BALANCE
@ -119,15 +136,10 @@ def test_minimal_penalty(spec, state):
spec.process_slashings(state)
yield 'post', state
expected_penalty = (
state.validators[0].effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
* (get_slashing_multiplier(spec) * total_penalties)
// total_balance
* spec.EFFECTIVE_BALANCE_INCREMENT
)
expected_penalty = _compute_expected_correlation_penalty(
spec, state.validators[0].effective_balance, total_penalties, total_balance)
assert expected_penalty == 0
assert state.balances[0] == pre_slash_balances[0]
assert state.balances[0] == pre_slash_balances[0] - expected_penalty
@with_all_phases
@ -181,12 +193,8 @@ def test_scaled_penalties(spec, state):
for i in slashed_indices:
v = state.validators[i]
expected_penalty = (
v.effective_balance // spec.EFFECTIVE_BALANCE_INCREMENT
* (get_slashing_multiplier(spec) * total_penalties)
// (total_balance)
* spec.EFFECTIVE_BALANCE_INCREMENT
)
expected_penalty = _compute_expected_correlation_penalty(
spec, v.effective_balance, total_penalties, total_balance)
assert state.balances[i] == pre_slash_balances[i] - expected_penalty