Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-7547: Inclusion Lists #3617

Open
wants to merge 38 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7d7398d
add full capella pyspec
michaelneuder May 21, 2023
07e713c
dev push for ils changes
michaelneuder Jan 22, 2024
eebbd6e
deneb update
michaelneuder Jan 22, 2024
fb3d2a3
Merge branch 'dev' of https://github.com/ethereum/consensus-specs int…
michaelneuder Mar 7, 2024
ffc3c76
remove old stuff
michaelneuder Mar 7, 2024
01b2f64
init commit
michaelneuder Mar 7, 2024
6984a1a
beacon chain
michaelneuder Mar 7, 2024
6c0c56a
fixes
michaelneuder Mar 7, 2024
42c122d
simplify
michaelneuder Mar 8, 2024
c7b1fd1
doctoc .
michaelneuder Mar 8, 2024
2e1b630
simplify
michaelneuder Mar 8, 2024
8114991
naming issue
michaelneuder Mar 8, 2024
d04d802
Update specs/_features/eip7547/p2p-networking.md
michaelneuder Mar 12, 2024
6599c32
Update specs/_features/eip7547/p2p-networking.md
michaelneuder Mar 12, 2024
2efaf1a
Update specs/_features/eip7547/p2p-networking.md
michaelneuder Mar 12, 2024
a11886c
Update specs/_features/eip7547/p2p-networking.md
michaelneuder Mar 12, 2024
d8d45bb
Update specs/_features/eip7547/p2p-networking.md
michaelneuder Mar 12, 2024
8970f6b
validator tweaks
michaelneuder Mar 12, 2024
d25b5d6
validate the inclusion list on_block
michaelneuder Mar 12, 2024
38f74d3
fix newline
michaelneuder Mar 12, 2024
90cf263
fix newline
michaelneuder Mar 12, 2024
7cb01ab
s/143/256
michaelneuder Mar 12, 2024
6dc2894
Make linter happy
hwwhww Mar 13, 2024
dcb206f
fix typo
hwwhww Mar 13, 2024
335b6b5
beacon-chain.md updates
michaelneuder Mar 18, 2024
995c049
beacon-chain.md updates
michaelneuder Mar 18, 2024
75aa52c
fork-choice.md
michaelneuder Mar 18, 2024
97cc84c
fork-choice.md
michaelneuder Mar 18, 2024
f46dd05
p2p-networking.md
michaelneuder Mar 18, 2024
0059893
validator.md
michaelneuder Mar 18, 2024
f0a13ab
small fixes
michaelneuder Mar 18, 2024
7545154
terence responses
michaelneuder Mar 19, 2024
c00b2d8
verify signature check
michaelneuder Mar 19, 2024
c82960d
signed summary in EL block
michaelneuder Mar 19, 2024
4d54445
fc changes
michaelneuder Mar 19, 2024
920fab1
keying on parent_hash too
michaelneuder Mar 19, 2024
086d20b
tweaks
michaelneuder Mar 21, 2024
37ca0c9
fork choice filter
michaelneuder Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ tests/core/pyspec/eth2spec/eip6110/
tests/core/pyspec/eth2spec/eip7002/
tests/core/pyspec/eth2spec/whisk/
tests/core/pyspec/eth2spec/eip7594/
tests/core/pyspec/eth2spec/eip7547/

# coverage reports
.htmlcov
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/*/*.md) \
$(wildcard $(SPEC_DIR)/_features/*/*/*.md) \
$(wildcard $(SSZ_DIR)/*.md)

ALL_EXECUTABLE_SPEC_NAMES = phase0 altair bellatrix capella deneb eip6110 eip7002 whisk
ALL_EXECUTABLE_SPEC_NAMES = phase0 altair bellatrix capella deneb eip6110 eip7002 whisk eip7547
# The parameters for commands. Use `foreach` to avoid listing specs again.
COVERAGE_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPEC_NAMES), --cov=eth2spec.$S.$(TEST_PRESET_TYPE))
PYLINT_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPEC_NAMES), ./eth2spec/$S)
Expand Down
3 changes: 3 additions & 0 deletions configs/mainnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ EIP7002_FORK_EPOCH: 18446744073709551615
# WHISK
WHISK_FORK_VERSION: 0x06000000 # temporary stub
WHISK_FORK_EPOCH: 18446744073709551615
# EIP7547
EIP7547_FORK_VERSION: 0x07000000 # temporary stub
EIP7547_FORK_EPOCH: 18446744073709551615


# Time parameters
Expand Down
3 changes: 3 additions & 0 deletions configs/minimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ EIP7002_FORK_EPOCH: 18446744073709551615
# WHISK
WHISK_FORK_VERSION: 0x06000001
WHISK_FORK_EPOCH: 18446744073709551615
# EIP7547
EIP7547_FORK_VERSION: 0x07000001
EIP7547_FORK_EPOCH: 18446744073709551615


# Time parameters
Expand Down
1 change: 1 addition & 0 deletions pysetup/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
EIP6110 = 'eip6110'
EIP7002 = 'eip7002'
WHISK = 'whisk'
EIP7547 = 'eip7547'
EIP7594 = 'eip7594'


Expand Down
2 changes: 2 additions & 0 deletions pysetup/md_doc_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
EIP6110,
WHISK,
EIP7002,
EIP7547,
EIP7594,
)

Expand All @@ -22,6 +23,7 @@
EIP6110: DENEB,
WHISK: CAPELLA,
EIP7002: CAPELLA,
EIP7547: DENEB,
EIP7594: DENEB,
}

Expand Down
3 changes: 2 additions & 1 deletion pysetup/spec_builders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
from .eip7002 import EIP7002SpecBuilder
from .whisk import WhiskSpecBuilder
from .eip7594 import EIP7594SpecBuilder
from .eip7547 import EIP7547SpecBuilder


spec_builders = {
builder.fork: builder
for builder in (
Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, DenebSpecBuilder,
EIP6110SpecBuilder, EIP7002SpecBuilder, WhiskSpecBuilder, EIP7594SpecBuilder,
EIP6110SpecBuilder, EIP7002SpecBuilder, WhiskSpecBuilder, EIP7594SpecBuilder, EIP7547SpecBuilder,
)
}
53 changes: 53 additions & 0 deletions pysetup/spec_builders/eip7547.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from .base import BaseSpecBuilder
from ..constants import EIP7547


class EIP7547SpecBuilder(BaseSpecBuilder):
fork: str = EIP7547

@classmethod
def sundry_functions(cls) -> str:
return '''
def retrieve_inclusion_list(slot: Slot, proposer_index: ValidatorIndex) -> InclusionList:
# pylint: disable=unused-argument
...
'''

@classmethod
def execution_engine_cls(cls) -> str:
return """
class NoopExecutionEngine(ExecutionEngine):
def notify_new_payload(self: ExecutionEngine,
execution_payload: ExecutionPayload,
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
def notify_new_inclusion_list(self: ExecutionEngine,
inclusion_list_request: NewInclusionListRequest) -> bool:
return True
def get_execution_inclusion_list(self: ExecutionEngine, parent_block_hash: Root) -> GetInclusionListResponse:
return GetInclusionListResponse()
EXECUTION_ENGINE = NoopExecutionEngine()"""

@classmethod
def imports(cls, preset_name: str):
return f'''
from eth2spec.deneb import {preset_name} as deneb
'''
251 changes: 251 additions & 0 deletions specs/_features/eip7547/beacon-chain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# EIP-7547 -- The Beacon Chain

## Table of contents

<!-- TOC -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Introduction](#introduction)
- [Constants](#constants)
- [Domain types](#domain-types)
- [Preset](#preset)
- [Execution](#execution)
- [Containers](#containers)
- [New Containers](#new-containers)
- [Extended containers](#extended-containers)
- [`ExecutionPayload`](#executionpayload)
- [`ExecutionPayloadHeader`](#executionpayloadheader)
- [`BeaconState`](#beaconstate)
- [Block processing](#block-processing)
- [Block header](#block-header)
- [Execution payload](#execution-payload)
- [Modified `process_execution_payload`](#modified-process_execution_payload)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->

## Introduction

This is the beacon chain specification to add an inclusion list mechanism to allow forced transaction inclusion. Refers to [EIP-7547](https://eips.ethereum.org/EIPS/eip-7547).

*Note:* This specification is built upon [Deneb](../../deneb/beacon_chain.md) and is under active development.

## Constants

### Domain types

| Name | Value |
| - | - |
| `DOMAIN_INCLUSION_LIST_SUMMARY` | `DomainType('0x0B000000')` |

## Preset

### Execution

| Name | Value |
| - | - |
| `MAX_TRANSACTIONS_PER_INCLUSION_LIST` | `uint64(143)` |

## Containers

### New Containers

```python
class SignedInclusionListSummary(Container):
summary: List[ExecutionAddress, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
michaelneuder marked this conversation as resolved.
Show resolved Hide resolved
signature: BLSSignature
```

### Extended containers

#### `ExecutionPayload`

```python
class ExecutionPayload(Container):
# Execution block header fields
parent_hash: Hash32
fee_recipient: ExecutionAddress # 'beneficiary' in the yellow paper
state_root: Bytes32
receipts_root: Bytes32
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
prev_randao: Bytes32 # 'difficulty' in the yellow paper
block_number: uint64 # 'number' in the yellow paper
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 # Hash of execution block
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
blob_gas_used: uint64
excess_blob_gas: uint64
previous_inclusion_list_summary: SignedInclusionListSummary # [New in EIP7547]
```

#### `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 # Hash of execution block
transactions_root: Root
withdrawals_root: Root
blob_gas_used: uint64
excess_blob_gas: uint64
previous_inclusion_list_summary_root: Root # [New in EIP7547]
```

#### `BeaconState`

```python
class BeaconState(Container):
# Versioning
genesis_time: uint64
genesis_validators_root: Root
slot: Slot
fork: Fork
# History
latest_block_header: BeaconBlockHeader
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
# Eth1
eth1_data: Eth1Data
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
eth1_deposit_index: uint64
# Registry
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
# Slashings
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
# Participation
previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
# Finality
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH] # Bit set for every recent justified epoch
previous_justified_checkpoint: Checkpoint
current_justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
# Inactivity
inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT]
# Sync
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# Execution
latest_execution_payload_header: ExecutionPayloadHeader
# Withdrawals
next_withdrawal_index: WithdrawalIndex
next_withdrawal_validator_index: ValidatorIndex
# Deep history valid from Capella onwards
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
# Needed for inclusion list validation
previous_proposer_index: ValidatorIndex # [New in EIP7547]
```

### Block processing

#### Block header

```python
def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
# Verify that the slots match
assert block.slot == state.slot
# Verify that the block is newer than latest block header
assert block.slot > state.latest_block_header.slot
# Verify that proposer index is the correct index
assert block.proposer_index == get_beacon_proposer_index(state)
# Verify that the parent matches
assert block.parent_root == hash_tree_root(state.latest_block_header)
# Set previous proposer index before overwriting latest block header
state.previous_proposer_index = state.latest_block_header.proposer_index # [New in EIP7547]
# Cache current block as the new latest block
state.latest_block_header = BeaconBlockHeader(
slot=block.slot,
proposer_index=block.proposer_index,
parent_root=block.parent_root,
state_root=Bytes32(), # Overwritten in the next process_slot call
body_root=hash_tree_root(block.body),
)

# Verify proposer is not slashed
proposer = state.validators[block.proposer_index]
assert not proposer.slashed
```

#### Execution payload

##### Modified `process_execution_payload`

```python
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
payload = body.execution_payload

# Verify consistency of the parent hash with respect to the previous execution payload header
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
# Verify prev_randao
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
# Verify timestamp
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
# [New in EIP7547] Verify previous proposer signature on inclusion list summary
assert verify_inclusion_list_summary_signature(state, payload.previous_inclusion_list_summary)

# Verify commitments are under limit
assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK

# Verify the execution payload is valid
versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments]
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,
)
)

# Cache execution payload header
state.latest_execution_payload_header = ExecutionPayloadHeader(
parent_hash=payload.parent_hash,
fee_recipient=payload.fee_recipient,
state_root=payload.state_root,
receipts_root=payload.receipts_root,
logs_bloom=payload.logs_bloom,
prev_randao=payload.prev_randao,
block_number=payload.block_number,
gas_limit=payload.gas_limit,
gas_used=payload.gas_used,
timestamp=payload.timestamp,
extra_data=payload.extra_data,
base_fee_per_gas=payload.base_fee_per_gas,
block_hash=payload.block_hash,
transactions_root=hash_tree_root(payload.transactions),
withdrawals_root=hash_tree_root(payload.withdrawals),
blob_gas_used=payload.blob_gas_used,
excess_blob_gas=payload.excess_blob_gas,
previous_inclusion_list_summary_root=hash_tree_root(payload.previous_inclusion_list_summary) # [New in EIP7547]
)
```

```python
def verify_inclusion_list_summary_signature(state: BeaconState, inclusion_list_summary: SignedInclusionListSummary) -> bool:
signing_root = compute_signing_root(inclusion_list_summary.message, get_domain(state, DOMAIN_INCLUSION_LIST_SUMMARY))
previous_proposer = state.validators[state.previous_proposer_index]
return bls.Verify(previous_proposer.pubkey, signing_root, inclusion_list_summary.signature)
```