build EIP 7045 into Deneb fork
This commit is contained in:
parent
559b89c447
commit
ec4bdae2d4
|
@ -168,20 +168,6 @@ jobs:
|
|||
command: make citest fork=eip6110
|
||||
- store_test_results:
|
||||
path: tests/core/pyspec/test-reports
|
||||
test-eip7045:
|
||||
docker:
|
||||
- image: circleci/python:3.8
|
||||
working_directory: ~/specs-repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: v3-specs-repo-{{ .Branch }}-{{ .Revision }}
|
||||
- restore_pyspec_cached_venv
|
||||
- run:
|
||||
name: Run py-tests
|
||||
command: make citest fork=eip7045
|
||||
- store_test_results:
|
||||
path: tests/core/pyspec/test-reports
|
||||
|
||||
table_of_contents:
|
||||
docker:
|
||||
- image: circleci/node:10.16.3
|
||||
|
@ -305,9 +291,6 @@ workflows:
|
|||
- test-eip6110:
|
||||
requires:
|
||||
- install_pyspec_test
|
||||
- test-eip7045:
|
||||
requires:
|
||||
- install_pyspec_test
|
||||
- table_of_contents
|
||||
- codespell
|
||||
- lint:
|
||||
|
|
2
Makefile
2
Makefile
|
@ -34,7 +34,7 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/*/*.md) \
|
|||
$(wildcard $(SPEC_DIR)/_features/*/*/*.md) \
|
||||
$(wildcard $(SSZ_DIR)/*.md)
|
||||
|
||||
ALL_EXECUTABLE_SPECS = phase0 altair bellatrix capella deneb eip6110 eip7045 whisk
|
||||
ALL_EXECUTABLE_SPECS = phase0 altair bellatrix capella deneb eip6110 whisk
|
||||
# The parameters for commands. Use `foreach` to avoid listing specs again.
|
||||
COVERAGE_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPECS), --cov=eth2spec.$S.$(TEST_PRESET_TYPE))
|
||||
PYLINT_SCOPE := $(foreach S,$(ALL_EXECUTABLE_SPECS), ./eth2spec/$S)
|
||||
|
|
|
@ -53,9 +53,6 @@ DENEB_FORK_EPOCH: 18446744073709551615
|
|||
# EIP6110
|
||||
EIP6110_FORK_VERSION: 0x05000000 # temporary stub
|
||||
EIP6110_FORK_EPOCH: 18446744073709551615
|
||||
# EIP7045
|
||||
EIP7045_FORK_VERSION: 0x05000000 # temporary stub
|
||||
EIP7045_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Time parameters
|
||||
|
|
|
@ -52,11 +52,6 @@ DENEB_FORK_EPOCH: 18446744073709551615
|
|||
# EIP6110
|
||||
EIP6110_FORK_VERSION: 0x05000001
|
||||
EIP6110_FORK_EPOCH: 18446744073709551615
|
||||
# EIP7045
|
||||
EIP7045_FORK_VERSION: 0x05000001
|
||||
EIP7045_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
|
||||
|
||||
# Time parameters
|
||||
|
|
16
setup.py
16
setup.py
|
@ -48,7 +48,6 @@ BELLATRIX = 'bellatrix'
|
|||
CAPELLA = 'capella'
|
||||
DENEB = 'deneb'
|
||||
EIP6110 = 'eip6110'
|
||||
EIP7045= 'eip7045'
|
||||
WHISK = 'whisk'
|
||||
|
||||
PREVIOUS_FORK_OF = {
|
||||
|
@ -58,7 +57,6 @@ PREVIOUS_FORK_OF = {
|
|||
CAPELLA: BELLATRIX,
|
||||
DENEB: CAPELLA,
|
||||
EIP6110: DENEB,
|
||||
EIP7045: DENEB,
|
||||
WHISK: CAPELLA,
|
||||
}
|
||||
|
||||
|
@ -778,18 +776,6 @@ class EIP6110SpecBuilder(DenebSpecBuilder):
|
|||
from eth2spec.deneb import {preset_name} as deneb
|
||||
'''
|
||||
|
||||
#
|
||||
# EIP7045SpecBuilder
|
||||
#
|
||||
class EIP7045SpecBuilder(DenebSpecBuilder):
|
||||
fork: str = EIP7045
|
||||
|
||||
@classmethod
|
||||
def imports(cls, preset_name: str):
|
||||
return super().imports(preset_name) + f'''
|
||||
from eth2spec.deneb import {preset_name} as deneb
|
||||
'''
|
||||
|
||||
#
|
||||
# WhiskSpecBuilder
|
||||
#
|
||||
|
@ -816,7 +802,7 @@ spec_builders = {
|
|||
builder.fork: builder
|
||||
for builder in (
|
||||
Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, DenebSpecBuilder,
|
||||
EIP6110SpecBuilder, EIP7045SpecBuilder, WhiskSpecBuilder,
|
||||
EIP6110SpecBuilder, WhiskSpecBuilder,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
# Deneb -- The Beacon Chain
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers.
|
||||
|
||||
## 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)
|
||||
- [Preset](#preset)
|
||||
- [Configuration](#configuration)
|
||||
- [Containers](#containers)
|
||||
- [Helpers](#helpers)
|
||||
- [Modified `get_attestation_participation_flag_indicies`](#modified-get_attestation_participation_flag_indicies)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Block processing](#block-processing)
|
||||
- [Modified `process_attestation`](#modified-process_attestation)
|
||||
- [Testing](#testing)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This feature allows for inclusion of attestations created during epoch `N` to be included in slots from epoch `N` as well as all slots in epoch `N+1` rather than the current `SLOTS_PER_EPOCH` slot restricted range. This is an extension of the Deneb upgrade.
|
||||
|
||||
## Preset
|
||||
|
||||
## Configuration
|
||||
|
||||
## Containers
|
||||
|
||||
## Helpers
|
||||
|
||||
### Modified `get_attestation_participation_flag_indicies`
|
||||
|
||||
*Note:* The function `get_attestation_participation_flag_indicies` is modified to set the `TIMELY_TARGET_FLAG` for any correct target attestation, regardless of `inclusion_delay` as a baseline reward for any speed of inclusion of an attestation that contributes to justification of the contained chain.
|
||||
|
||||
```python
|
||||
def get_attestation_participation_flag_indices(state: BeaconState,
|
||||
data: AttestationData,
|
||||
inclusion_delay: uint64) -> Sequence[int]:
|
||||
"""
|
||||
Return the flag indices that are satisfied by an attestation.
|
||||
"""
|
||||
if data.target.epoch == get_current_epoch(state):
|
||||
justified_checkpoint = state.current_justified_checkpoint
|
||||
else:
|
||||
justified_checkpoint = state.previous_justified_checkpoint
|
||||
|
||||
# Matching roots
|
||||
is_matching_source = data.source == justified_checkpoint
|
||||
is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
|
||||
is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot)
|
||||
assert is_matching_source
|
||||
|
||||
participation_flag_indices = []
|
||||
if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH):
|
||||
participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
|
||||
if is_matching_target: # [Modified in EIP7045]
|
||||
participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)
|
||||
if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
|
||||
participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
|
||||
|
||||
return participation_flag_indices
|
||||
```
|
||||
|
||||
## Beacon chain state transition function
|
||||
|
||||
### Block processing
|
||||
|
||||
#### Modified `process_attestation`
|
||||
|
||||
*Note*: The function `process_attestation` is modified to expand valid slots for inclusion to those in both `target.epoch` epoch and `target.epoch + 1` epoch. Additionally, it utilizes an updated version of `get_attestation_participation_flag_indices` to ensure rewards are available for the extended attestation inclusion range.
|
||||
|
||||
```python
|
||||
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
data = attestation.data
|
||||
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
||||
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot # [Modified in EIP7045]
|
||||
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
||||
|
||||
committee = get_beacon_committee(state, data.slot, data.index)
|
||||
assert len(attestation.aggregation_bits) == len(committee)
|
||||
|
||||
# Participation flag indices
|
||||
participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot)
|
||||
|
||||
# Verify signature
|
||||
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
||||
|
||||
# Update epoch participation flags
|
||||
if data.target.epoch == get_current_epoch(state):
|
||||
epoch_participation = state.current_epoch_participation
|
||||
else:
|
||||
epoch_participation = state.previous_epoch_participation
|
||||
|
||||
proposer_reward_numerator = 0
|
||||
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
||||
for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
|
||||
if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
|
||||
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
|
||||
proposer_reward_numerator += get_base_reward(state, index) * weight
|
||||
|
||||
# Reward proposer
|
||||
proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
|
||||
proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
|
||||
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP7045 testing only.
|
||||
Modifications include:
|
||||
1. Use `EIP7045_FORK_VERSION` as the previous and current fork version.
|
||||
|
||||
```python
|
||||
def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
|
||||
eth1_timestamp: uint64,
|
||||
deposits: Sequence[Deposit],
|
||||
execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader()
|
||||
) -> BeaconState:
|
||||
fork = Fork(
|
||||
previous_version=EIP7045_FORK_VERSION, # [Modified in EIP7045] for testing only
|
||||
current_version=EIP7045_FORK_VERSION, # [Modified in EIP7045]
|
||||
epoch=GENESIS_EPOCH,
|
||||
)
|
||||
state = BeaconState(
|
||||
genesis_time=eth1_timestamp + GENESIS_DELAY,
|
||||
fork=fork,
|
||||
eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
|
||||
latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
|
||||
randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
|
||||
)
|
||||
|
||||
# Process deposits
|
||||
leaves = list(map(lambda deposit: deposit.data, deposits))
|
||||
for index, deposit in enumerate(deposits):
|
||||
deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
|
||||
state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
|
||||
process_deposit(state, deposit)
|
||||
|
||||
# Process activations
|
||||
for index, validator in enumerate(state.validators):
|
||||
balance = state.balances[index]
|
||||
validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
|
||||
validator.activation_eligibility_epoch = GENESIS_EPOCH
|
||||
validator.activation_epoch = GENESIS_EPOCH
|
||||
|
||||
# Set genesis validators root for domain separation and chain versioning
|
||||
state.genesis_validators_root = hash_tree_root(state.validators)
|
||||
|
||||
# Fill in sync committees
|
||||
# Note: A duplicate committee is assigned for the current and next committee at genesis
|
||||
state.current_sync_committee = get_next_sync_committee(state)
|
||||
state.next_sync_committee = get_next_sync_committee(state)
|
||||
|
||||
# Initialize the execution payload header
|
||||
state.latest_execution_payload_header = execution_payload_header
|
||||
|
||||
return state
|
||||
```
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
# Att-Slot-Range -- Fork Logic
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers.
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- 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)
|
||||
- [Configuration](#configuration)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [Modified `compute_fork_version`](#modified-compute_fork_version)
|
||||
- [Fork to EIP7045](#fork-to-eip7045)
|
||||
- [Fork trigger](#fork-trigger)
|
||||
- [Upgrading the state](#upgrading-the-state)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes the process of Att-Slot-Range upgrade.
|
||||
|
||||
## Configuration
|
||||
|
||||
Warning: this configuration is not definitive.
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `EIP7045_FORK_VERSION` | `Version('0x05000000')` |
|
||||
| `EIP7045_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
|
||||
|
||||
## Helper functions
|
||||
|
||||
### Misc
|
||||
|
||||
#### Modified `compute_fork_version`
|
||||
|
||||
```python
|
||||
def compute_fork_version(epoch: Epoch) -> Version:
|
||||
"""
|
||||
Return the fork version at the given ``epoch``.
|
||||
"""
|
||||
if epoch >= EIP7045_FORK_EPOCH:
|
||||
return EIP7045_FORK_VERSION
|
||||
if epoch >= DENEB_FORK_EPOCH:
|
||||
return DENEB_FORK_VERSION
|
||||
if epoch >= CAPELLA_FORK_EPOCH:
|
||||
return CAPELLA_FORK_VERSION
|
||||
if epoch >= BELLATRIX_FORK_EPOCH:
|
||||
return BELLATRIX_FORK_VERSION
|
||||
if epoch >= ALTAIR_FORK_EPOCH:
|
||||
return ALTAIR_FORK_VERSION
|
||||
return GENESIS_FORK_VERSION
|
||||
```
|
||||
|
||||
## Fork to EIP7045
|
||||
|
||||
### Fork trigger
|
||||
|
||||
TBD. This fork is defined for testing purposes, the EIP may be combined with other consensus-layer upgrade.
|
||||
For now, we assume the condition will be triggered at epoch `EIP7045_FORK_EPOCH`.
|
||||
|
||||
Note that for the pure EIP7045 networks, we don't apply `upgrade_to_eip7045` since it starts with EIP7045 version logic.
|
||||
|
||||
### Upgrading the state
|
||||
|
||||
If `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == EIP7045_FORK_EPOCH`,
|
||||
an irregular state change is made to upgrade to EIP7045.
|
||||
|
||||
```python
|
||||
def upgrade_to_eip7045(pre: deneb.BeaconState) -> BeaconState:
|
||||
post = BeaconState(
|
||||
# Versioning
|
||||
genesis_time=pre.genesis_time,
|
||||
genesis_validators_root=pre.genesis_validators_root,
|
||||
slot=pre.slot,
|
||||
fork=Fork(
|
||||
previous_version=pre.fork.current_version,
|
||||
current_version=EIP7045_FORK_VERSION, # [Modified in Att-Slot-Range]
|
||||
epoch=deneb.get_current_epoch(pre),
|
||||
),
|
||||
# History
|
||||
latest_block_header=pre.latest_block_header,
|
||||
block_roots=pre.block_roots,
|
||||
state_roots=pre.state_roots,
|
||||
historical_roots=pre.historical_roots,
|
||||
# Eth1
|
||||
eth1_data=pre.eth1_data,
|
||||
eth1_data_votes=pre.eth1_data_votes,
|
||||
eth1_deposit_index=pre.eth1_deposit_index,
|
||||
# Registry
|
||||
validators=pre.validators,
|
||||
balances=pre.balances,
|
||||
# Randomness
|
||||
randao_mixes=pre.randao_mixes,
|
||||
# Slashings
|
||||
slashings=pre.slashings,
|
||||
# Participation
|
||||
previous_epoch_participation=pre.previous_epoch_participation,
|
||||
current_epoch_participation=pre.current_epoch_participation,
|
||||
# Finality
|
||||
justification_bits=pre.justification_bits,
|
||||
previous_justified_checkpoint=pre.previous_justified_checkpoint,
|
||||
current_justified_checkpoint=pre.current_justified_checkpoint,
|
||||
finalized_checkpoint=pre.finalized_checkpoint,
|
||||
# Inactivity
|
||||
inactivity_scores=pre.inactivity_scores,
|
||||
# Sync
|
||||
current_sync_committee=pre.current_sync_committee,
|
||||
next_sync_committee=pre.next_sync_committee,
|
||||
# Execution-layer
|
||||
latest_execution_payload_header=pre.latest_execution_payload_header,
|
||||
# Withdrawals
|
||||
next_withdrawal_index=pre.next_withdrawal_index,
|
||||
next_withdrawal_validator_index=pre.next_withdrawal_validator_index,
|
||||
# Deep history valid from Capella onwards
|
||||
historical_summaries=pre.historical_summaries,
|
||||
)
|
||||
|
||||
return post
|
||||
```
|
|
@ -1,72 +0,0 @@
|
|||
# EIP7045 -- Networking
|
||||
|
||||
This document contains the consensus-layer networking specification for EIP7045.
|
||||
|
||||
The specification of these changes continues in the same format as the network specifications of previous upgrades, and assumes them as pre-requisite.
|
||||
|
||||
## 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 -->
|
||||
|
||||
- [Modifications in EIP7045](#modifications-in-eip7045)
|
||||
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
|
||||
- [Topics and messages](#topics-and-messages)
|
||||
- [Global topics](#global-topics)
|
||||
- [`beacon_aggregate_and_proof`](#beacon_aggregate_and_proof)
|
||||
- [Attestation subnets](#attestation-subnets)
|
||||
- [`beacon_attestation_{subnet_id}](#beacon_attestation_subnet_id)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
||||
## Modifications in EIP7045
|
||||
|
||||
### The gossip domain: gossipsub
|
||||
|
||||
#### Topics and messages
|
||||
|
||||
Topics follow the same specification as in prior upgrades.
|
||||
|
||||
The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are modified to support the gossip of attestations created in epoch `N` to be gossiped through the entire range of slots in epoch `N+1` rather than only through one epoch of slots.
|
||||
|
||||
Otherwise, the specification around the creation, validation, and dissemination of messages has not changed from the Deneb document unless explicitly noted here.
|
||||
|
||||
The derivation of the `message-id` remains stable.
|
||||
|
||||
##### Global topics
|
||||
|
||||
Deneb introduces new global topics for blob sidecars.
|
||||
|
||||
###### `beacon_aggregate_and_proof`
|
||||
|
||||
The following validation is removed:
|
||||
* _[IGNORE]_ `aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate.data.slot`
|
||||
(a client MAY queue future aggregates for processing at the appropriate slot).
|
||||
|
||||
The following validations are added in its place:
|
||||
* _[IGNORE]_ `aggregate.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `aggregate.data.slot <= current_slot`
|
||||
(a client MAY queue future aggregates for processing at the appropriate slot).
|
||||
* _[IGNORE]_ the epoch of `aggregate.data.slot` is either the current or previous epoch
|
||||
(with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `compute_epoch_at_slot(aggregate.data.slot) in (get_previous_epoch(state), get_current_epoch(state))`
|
||||
|
||||
#### Attestation subnets
|
||||
|
||||
##### `beacon_attestation_{subnet_id}
|
||||
|
||||
The following validation is removed:
|
||||
* _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot`
|
||||
(a client MAY queue future attestations for processing at the appropriate slot).
|
||||
|
||||
The following validations are added in its place:
|
||||
* _[IGNORE]_ `attestation.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `attestation.data.slot <= current_slot`
|
||||
(a client MAY queue future attestation for processing at the appropriate slot).
|
||||
* _[IGNORE]_ the epoch of `attestation.data.slot` is either the current or previous epoch
|
||||
(with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `compute_epoch_at_slot(attestation.data.slot) in (get_previous_epoch(state), get_current_epoch(state))`
|
|
@ -24,6 +24,7 @@
|
|||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash)
|
||||
- [Modified `get_attestation_participation_flag_indicies`](#modified-get_attestation_participation_flag_indicies)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Execution engine](#execution-engine)
|
||||
- [Request data](#request-data)
|
||||
|
@ -32,6 +33,7 @@
|
|||
- [`is_valid_versioned_hashes`](#is_valid_versioned_hashes)
|
||||
- [Modified `verify_and_notify_new_payload`](#modified-verify_and_notify_new_payload)
|
||||
- [Block processing](#block-processing)
|
||||
- [Modified `process_attestation`](#modified-process_attestation)
|
||||
- [Execution payload](#execution-payload)
|
||||
- [Modified `process_execution_payload`](#modified-process_execution_payload)
|
||||
- [Modified `process_voluntary_exit`](#modified-process_voluntary_exit)
|
||||
|
@ -45,6 +47,7 @@
|
|||
Deneb is a consensus-layer upgrade containing a number of features. Including:
|
||||
* [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844): Shard Blob Transactions scale data-availability of Ethereum in a simple, forwards-compatible manner
|
||||
* [EIP-7044](https://github.com/ethereum/EIPs/pull/7044): Perpetually Valid Signed Voluntary Exits
|
||||
* [EIP-7045](https://eips.ethereum.org/EIPS/eip-7045): Increase Max Attestation Inclusion Slot
|
||||
|
||||
## Custom types
|
||||
|
||||
|
@ -170,6 +173,40 @@ def kzg_commitment_to_versioned_hash(kzg_commitment: KZGCommitment) -> Versioned
|
|||
return VERSIONED_HASH_VERSION_KZG + hash(kzg_commitment)[1:]
|
||||
```
|
||||
|
||||
### Modified `get_attestation_participation_flag_indicies`
|
||||
|
||||
*Note:* The function `get_attestation_participation_flag_indicies` is modified to set the `TIMELY_TARGET_FLAG` for any correct target attestation, regardless of `inclusion_delay` as a baseline reward for any speed of inclusion of an attestation that contributes to justification of the contained chain for EIP-7045.
|
||||
|
||||
```python
|
||||
def get_attestation_participation_flag_indices(state: BeaconState,
|
||||
data: AttestationData,
|
||||
inclusion_delay: uint64) -> Sequence[int]:
|
||||
"""
|
||||
Return the flag indices that are satisfied by an attestation.
|
||||
"""
|
||||
if data.target.epoch == get_current_epoch(state):
|
||||
justified_checkpoint = state.current_justified_checkpoint
|
||||
else:
|
||||
justified_checkpoint = state.previous_justified_checkpoint
|
||||
|
||||
# Matching roots
|
||||
is_matching_source = data.source == justified_checkpoint
|
||||
is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
|
||||
is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot)
|
||||
assert is_matching_source
|
||||
|
||||
participation_flag_indices = []
|
||||
if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH):
|
||||
participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
|
||||
if is_matching_target: # [Modified in Deneb:EIP7045]
|
||||
participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)
|
||||
if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
|
||||
participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
|
||||
|
||||
return participation_flag_indices
|
||||
```
|
||||
|
||||
|
||||
## Beacon chain state transition function
|
||||
|
||||
### Execution engine
|
||||
|
@ -221,10 +258,52 @@ def verify_and_notify_new_payload(self: ExecutionEngine,
|
|||
|
||||
### Block processing
|
||||
|
||||
#### Modified `process_attestation`
|
||||
|
||||
*Note*: The function `process_attestation` is modified to expand valid slots for inclusion to those in both `target.epoch` epoch and `target.epoch + 1` epoch for EIP-7045. Additionally, it utilizes an updated version of `get_attestation_participation_flag_indices` to ensure rewards are available for the extended attestation inclusion range for EIP-7045.
|
||||
|
||||
```python
|
||||
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
data = attestation.data
|
||||
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
||||
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot # [Modified in Deneb:EIP7045]
|
||||
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
||||
|
||||
committee = get_beacon_committee(state, data.slot, data.index)
|
||||
assert len(attestation.aggregation_bits) == len(committee)
|
||||
|
||||
# Participation flag indices
|
||||
participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot)
|
||||
|
||||
# Verify signature
|
||||
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
||||
|
||||
# Update epoch participation flags
|
||||
if data.target.epoch == get_current_epoch(state):
|
||||
epoch_participation = state.current_epoch_participation
|
||||
else:
|
||||
epoch_participation = state.previous_epoch_participation
|
||||
|
||||
proposer_reward_numerator = 0
|
||||
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
||||
for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
|
||||
if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
|
||||
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
|
||||
proposer_reward_numerator += get_base_reward(state, index) * weight
|
||||
|
||||
# Reward proposer
|
||||
proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
|
||||
proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
|
||||
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||
```
|
||||
|
||||
#### Execution payload
|
||||
|
||||
##### Modified `process_execution_payload`
|
||||
|
||||
*Note*: The function `process_execution_payload` is modified to pass `versioned_hashes` into `execution_engine.verify_and_notify_new_payload` and to assign the new fields in `ExecutionPayloadHeader` for EIP-4844.
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
|
||||
payload = body.execution_payload
|
||||
|
@ -270,7 +349,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi
|
|||
|
||||
#### Modified `process_voluntary_exit`
|
||||
|
||||
*Note*: The function `process_voluntary_exit` is modified to use the a fixed fork version -- `CAPELLA_FORK_VERSION` -- for EIP-7044
|
||||
*Note*: The function `process_voluntary_exit` is modified to use the a fixed fork version -- `CAPELLA_FORK_VERSION` -- for EIP-7044.
|
||||
|
||||
```python
|
||||
def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
|
||||
|
|
|
@ -57,7 +57,7 @@ def compute_fork_version(epoch: Epoch) -> Version:
|
|||
|
||||
### Fork trigger
|
||||
|
||||
TBD. This fork is defined for testing purposes, the EIP may be combined with other consensus-layer upgrade.
|
||||
TBD. This fork is defined for testing purposes.
|
||||
For now, we assume the condition will be triggered at epoch `DENEB_FORK_EPOCH`.
|
||||
|
||||
Note that for the pure Deneb networks, we don't apply `upgrade_to_deneb` since it starts with Deneb version logic.
|
||||
|
|
|
@ -23,6 +23,9 @@ The specification of these changes continues in the same format as the network s
|
|||
- [Global topics](#global-topics)
|
||||
- [`beacon_block`](#beacon_block)
|
||||
- [`blob_sidecar_{subnet_id}`](#blob_sidecar_subnet_id)
|
||||
- [`beacon_aggregate_and_proof`](#beacon_aggregate_and_proof)
|
||||
- [Attestation subnets](#attestation-subnets)
|
||||
- [`beacon_attestation_{subnet_id}](#beacon_attestation_subnet_id)
|
||||
- [Transitioning the gossip](#transitioning-the-gossip)
|
||||
- [The Req/Resp domain](#the-reqresp-domain)
|
||||
- [Messages](#messages)
|
||||
|
@ -106,7 +109,11 @@ Some gossip meshes are upgraded in the fork of Deneb to support upgraded types.
|
|||
|
||||
Topics follow the same specification as in prior upgrades.
|
||||
|
||||
The `beacon_block` topic is modified to also support deneb blocks and new topics are added per table below. All other topics remain stable.
|
||||
The `beacon_block` topic is modified to also support Deneb blocks and new topics are added per table below.
|
||||
|
||||
The `voluntary_exit` topic is implicitly modified due to the lock-in use of `CAPELLA_FORK_VERSION` for this message signature validation for EIP-7044.
|
||||
|
||||
The `beacon_aggregate_and_proof` and `beacon_attestation_{subnet_id}` topics are modified to support the gossip of attestations created in epoch `N` to be gossiped through the entire range of slots in epoch `N+1` rather than only through one epoch of slots for EIP-7045.
|
||||
|
||||
The specification around the creation, validation, and dissemination of messages has not changed from the Capella document unless explicitly noted here.
|
||||
|
||||
|
@ -124,7 +131,9 @@ Deneb introduces new global topics for blob sidecars.
|
|||
|
||||
###### `beacon_block`
|
||||
|
||||
The *type* of the payload of this topic changes to the (modified) `SignedBeaconBlock` found in deneb.
|
||||
The *type* of the payload of this topic changes to the (modified) `SignedBeaconBlock` found in Deneb.
|
||||
|
||||
*[Modified in Deneb:EIP4844]*
|
||||
|
||||
New validation:
|
||||
|
||||
|
@ -150,6 +159,41 @@ The following validations MUST pass before forwarding the `signed_blob_sidecar`
|
|||
- _[REJECT]_ The sidecar is proposed by the expected `proposer_index` for the block's slot in the context of the current shuffling (defined by `block_parent_root`/`slot`).
|
||||
If the `proposer_index` cannot immediately be verified against the expected shuffling, the sidecar MAY be queued for later processing while proposers for the block's branch are calculated -- in such a case _do not_ `REJECT`, instead `IGNORE` this message.
|
||||
|
||||
###### `beacon_aggregate_and_proof`
|
||||
|
||||
*[Modified in Deneb:EIP7045]*
|
||||
|
||||
The following validation is removed:
|
||||
* _[IGNORE]_ `aggregate.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate.data.slot`
|
||||
(a client MAY queue future aggregates for processing at the appropriate slot).
|
||||
|
||||
The following validations are added in its place:
|
||||
* _[IGNORE]_ `aggregate.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `aggregate.data.slot <= current_slot`
|
||||
(a client MAY queue future aggregates for processing at the appropriate slot).
|
||||
* _[IGNORE]_ the epoch of `aggregate.data.slot` is either the current or previous epoch
|
||||
(with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `compute_epoch_at_slot(aggregate.data.slot) in (get_previous_epoch(state), get_current_epoch(state))`
|
||||
|
||||
##### Attestation subnets
|
||||
|
||||
###### `beacon_attestation_{subnet_id}
|
||||
|
||||
*[Modified in Deneb:EIP7045]*
|
||||
|
||||
The following validation is removed:
|
||||
* _[IGNORE]_ `attestation.data.slot` is within the last `ATTESTATION_PROPAGATION_SLOT_RANGE` slots (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot`
|
||||
(a client MAY queue future attestations for processing at the appropriate slot).
|
||||
|
||||
The following validations are added in its place:
|
||||
* _[IGNORE]_ `attestation.data.slot` is equal to or earlier than the `current_slot` (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `attestation.data.slot <= current_slot`
|
||||
(a client MAY queue future attestation for processing at the appropriate slot).
|
||||
* _[IGNORE]_ the epoch of `attestation.data.slot` is either the current or previous epoch
|
||||
(with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
||||
i.e. `compute_epoch_at_slot(attestation.data.slot) in (get_previous_epoch(state), get_current_epoch(state))`
|
||||
|
||||
#### Transitioning the gossip
|
||||
|
||||
|
|
|
@ -1002,7 +1002,7 @@ Clients MAY connect to peers with the same `fork_digest` but a different `next_f
|
|||
Unless `ENRForkID` is manually updated to matching prior to the earlier `next_fork_epoch` of the two clients,
|
||||
these connecting clients will be unable to successfully interact starting at the earlier `next_fork_epoch`.
|
||||
|
||||
### Attestation subnet subcription
|
||||
### Attestation subnet subscription
|
||||
|
||||
Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each beacon node should:
|
||||
|
||||
|
|
|
@ -9,13 +9,12 @@ from eth2spec.bellatrix import mainnet as spec_bellatrix_mainnet, minimal as spe
|
|||
from eth2spec.capella import mainnet as spec_capella_mainnet, minimal as spec_capella_minimal
|
||||
from eth2spec.deneb import mainnet as spec_deneb_mainnet, minimal as spec_deneb_minimal
|
||||
from eth2spec.eip6110 import mainnet as spec_eip6110_mainnet, minimal as spec_eip6110_minimal
|
||||
from eth2spec.eip7045 import mainnet as spec_eip7045_mainnet, minimal as spec_eip7045_minimal
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
EIP6110, EIP7045,
|
||||
EIP6110,
|
||||
MINIMAL, MAINNET,
|
||||
ALL_PHASES,
|
||||
ALL_FORK_UPGRADES,
|
||||
|
@ -84,7 +83,6 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
|||
CAPELLA: spec_capella_minimal,
|
||||
DENEB: spec_deneb_minimal,
|
||||
EIP6110: spec_eip6110_minimal,
|
||||
EIP7045: spec_eip7045_minimal,
|
||||
},
|
||||
MAINNET: {
|
||||
PHASE0: spec_phase0_mainnet,
|
||||
|
@ -93,7 +91,6 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
|||
CAPELLA: spec_capella_mainnet,
|
||||
DENEB: spec_deneb_mainnet,
|
||||
EIP6110: spec_eip6110_mainnet,
|
||||
EIP7045: spec_eip7045_mainnet,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -544,9 +541,6 @@ with_bellatrix_and_later = with_all_phases_from(BELLATRIX)
|
|||
with_capella_and_later = with_all_phases_from(CAPELLA)
|
||||
with_deneb_and_later = with_all_phases_from(DENEB)
|
||||
with_eip6110_and_later = with_all_phases_from(EIP6110)
|
||||
with_eip7045_and_later = with_all_phases_from(EIP7045)
|
||||
|
||||
with_all_phases_except_eip7045 = with_all_phases_except(EIP7045)
|
||||
|
||||
|
||||
class quoted_str(str):
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from eth2spec.test.context import (
|
||||
always_bls,
|
||||
spec_state_test,
|
||||
with_phases,
|
||||
with_deneb_and_later,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
|
|
|
@ -5,7 +5,7 @@ from typing import List
|
|||
from eth2spec.test.context import expect_assertion_error
|
||||
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_epoch, next_slot
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
from eth2spec.test.helpers.forks import is_post_altair, is_post_eip7045
|
||||
from eth2spec.test.helpers.forks import is_post_altair, is_post_deneb
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
|
@ -159,7 +159,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey):
|
|||
|
||||
|
||||
def compute_max_inclusion_slot(spec, attestation):
|
||||
if is_post_eip7045(spec):
|
||||
if is_post_deneb(spec):
|
||||
next_epoch = spec.compute_epoch_at_slot(attestation.data.slot) + 1
|
||||
end_of_next_epoch = spec.compute_start_slot_at_epoch(next_epoch + 1) - 1
|
||||
return end_of_next_epoch
|
||||
|
|
|
@ -17,7 +17,6 @@ SHARDING = SpecForkName('sharding')
|
|||
CUSTODY_GAME = SpecForkName('custody_game')
|
||||
DAS = SpecForkName('das')
|
||||
EIP6110 = SpecForkName('eip6110')
|
||||
EIP7045 = SpecForkName('eip7045')
|
||||
|
||||
#
|
||||
# SpecFork settings
|
||||
|
@ -32,7 +31,7 @@ ALL_PHASES = (
|
|||
*MAINNET_FORKS,
|
||||
DENEB,
|
||||
# Experimental patches
|
||||
EIP6110, EIP7045,
|
||||
EIP6110,
|
||||
)
|
||||
# The forks that have light client specs
|
||||
LIGHT_CLIENT_TESTING_FORKS = (*[item for item in MAINNET_FORKS if item != PHASE0], DENEB)
|
||||
|
|
|
@ -16,7 +16,6 @@ from eth2spec.test.helpers.constants import (
|
|||
CAPELLA,
|
||||
DENEB,
|
||||
EIP6110,
|
||||
EIP7045,
|
||||
)
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
prepare_state_and_deposit,
|
||||
|
@ -162,8 +161,6 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, sync_aggregate=
|
|||
state = post_spec.upgrade_to_deneb(state)
|
||||
elif post_spec.fork == EIP6110:
|
||||
state = post_spec.upgrade_to_eip6110(state)
|
||||
elif post_spec.fork == EIP7045:
|
||||
state = post_spec.upgrade_to_eip7045(state)
|
||||
|
||||
assert state.fork.epoch == fork_epoch
|
||||
|
||||
|
@ -182,9 +179,6 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, sync_aggregate=
|
|||
elif post_spec.fork == EIP6110:
|
||||
assert state.fork.previous_version == post_spec.config.DENEB_FORK_VERSION
|
||||
assert state.fork.current_version == post_spec.config.EIP6110_FORK_VERSION
|
||||
elif post_spec.fork == EIP7045:
|
||||
assert state.fork.previous_version == post_spec.config.DENEB_FORK_VERSION
|
||||
assert state.fork.current_version == post_spec.config.EIP7045_FORK_VERSION
|
||||
|
||||
if with_block:
|
||||
return state, _state_transition_and_sign_block_at_slot(
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
from .constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
|
||||
EIP6110, EIP7045,
|
||||
EIP6110,
|
||||
)
|
||||
|
||||
|
||||
def is_post_fork(a, b):
|
||||
if a == EIP7045:
|
||||
return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP7045]
|
||||
if a == EIP6110:
|
||||
return b in [PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110]
|
||||
if a == DENEB:
|
||||
|
@ -40,7 +38,3 @@ def is_post_deneb(spec):
|
|||
|
||||
def is_post_eip6110(spec):
|
||||
return is_post_fork(spec.fork, EIP6110)
|
||||
|
||||
|
||||
def is_post_eip7045(spec):
|
||||
return is_post_fork(spec.fork, EIP7045)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.helpers.constants import (
|
||||
ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110, EIP7045,
|
||||
ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110,
|
||||
)
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
compute_el_header_block_hash,
|
||||
|
@ -86,9 +86,6 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
|
|||
elif spec.fork == EIP6110:
|
||||
previous_version = spec.config.DENEB_FORK_VERSION
|
||||
current_version = spec.config.EIP6110_FORK_VERSION
|
||||
elif spec.fork == EIP7045:
|
||||
previous_version = spec.config.DENEB_FORK_VERSION
|
||||
current_version = spec.config.EIP7045_FORK_VERSION
|
||||
|
||||
state = spec.BeaconState(
|
||||
genesis_time=0,
|
||||
|
|
Loading…
Reference in New Issue