commit
5f1b88f6fd
|
@ -0,0 +1,133 @@
|
|||
name: Run spec tests and linter
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: zsh {0}
|
||||
|
||||
env:
|
||||
TEST_PRESET_TYPE: "minimal"
|
||||
DEFAULT_BRANCH: "dev"
|
||||
|
||||
# Run tests on workflow_Dispatch
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- master
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_preset_type:
|
||||
default: minimal
|
||||
description: Type of test to run, either mainnet or minimal
|
||||
type: string
|
||||
required: true
|
||||
commitRef:
|
||||
description: The branch, tag or SHA to checkout and build from
|
||||
default: dev
|
||||
required: true
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
precleanup:
|
||||
runs-on: self-hosted
|
||||
if: always()
|
||||
steps:
|
||||
- name: 'Cleanup build folder'
|
||||
run: |
|
||||
ls -la ./
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
ls -la ./
|
||||
setup-env:
|
||||
runs-on: self-hosted
|
||||
needs: precleanup
|
||||
steps:
|
||||
- name: Checkout this repo
|
||||
uses: actions/checkout@v3.2.0
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commitRef || env.DEFAULT_BRANCH }}
|
||||
- uses: actions/cache@v3.2.2
|
||||
id: cache-git
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
|
||||
table_of_contents:
|
||||
runs-on: self-hosted
|
||||
needs: setup-env
|
||||
steps:
|
||||
- uses: actions/cache@v3.2.2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- name: Check table of contents
|
||||
run: sudo npm install -g doctoc@2 && make check_toc
|
||||
|
||||
codespell:
|
||||
runs-on: self-hosted
|
||||
needs: setup-env
|
||||
steps:
|
||||
- name: Check codespell
|
||||
run: pip install 'codespell<3.0.0,>=2.0.0' --user && make codespell
|
||||
|
||||
lint:
|
||||
runs-on: self-hosted
|
||||
needs: setup-env
|
||||
steps:
|
||||
- name: Run linter for pyspec
|
||||
run: make lint
|
||||
- name: Run linter for test generators
|
||||
run: make lint_generators
|
||||
|
||||
pyspec-tests:
|
||||
runs-on: self-hosted
|
||||
needs: [setup-env,lint,codespell,table_of_contents]
|
||||
strategy:
|
||||
matrix:
|
||||
version: ["phase0", "altair", "bellatrix", "capella", "eip4844"]
|
||||
steps:
|
||||
- uses: actions/cache@v3.2.2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- name: set TEST_PRESET_TYPE
|
||||
if: github.event.inputs.test_preset_type != ''
|
||||
run: |
|
||||
echo "spec_test_preset_type=${{ github.event.inputs.test_preset_type || env.TEST_PRESET_TYPE }}" >> $GITHUB_ENV
|
||||
- name: set TEST_PRESET_TYPE
|
||||
if: ${{ (github.event_name == 'push' && github.ref_name != 'master') || github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
echo "spec_test_preset_type=${{ env.TEST_PRESET_TYPE}}" >> $GITHUB_ENV
|
||||
- name: set TEST_PRESET_TYPE
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'master' }}
|
||||
run: |
|
||||
echo "spec_test_preset_type=mainnet" >> $GITHUB_ENV
|
||||
- name: set TEST_PRESET_TYPE
|
||||
if: github.event.schedule=='0 0 * * *'
|
||||
run: |
|
||||
echo "spec_test_preset_type=mainnet" >> $GITHUB_ENV
|
||||
- name: Install pyspec requirements
|
||||
run: make install_test
|
||||
- name: test-${{ matrix.version }}
|
||||
run: make citest fork=${{ matrix.version }} TEST_PRESET_TYPE=${{env.spec_test_preset_type}}
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: test-${{ matrix.version }}
|
||||
path: tests/core/pyspec/test-reports
|
||||
|
||||
cleanup:
|
||||
runs-on: self-hosted
|
||||
needs: [setup-env,pyspec-tests,codespell,lint,table_of_contents]
|
||||
if: always()
|
||||
steps:
|
||||
- name: 'Cleanup build folder'
|
||||
run: |
|
||||
ls -la ./
|
||||
rm -rf ./* || true
|
||||
rm -rf ./.??* || true
|
||||
ls -la ./
|
18
Makefile
18
Makefile
|
@ -13,7 +13,7 @@ SOLIDITY_DEPOSIT_CONTRACT_SOURCE = ${SOLIDITY_DEPOSIT_CONTRACT_DIR}/deposit_cont
|
|||
SOLIDITY_FILE_NAME = deposit_contract.json
|
||||
DEPOSIT_CONTRACT_TESTER_DIR = ${SOLIDITY_DEPOSIT_CONTRACT_DIR}/web3_tester
|
||||
CONFIGS_DIR = ./configs
|
||||
|
||||
TEST_PRESET_TYPE ?= minimal
|
||||
# Collect a list of generator names
|
||||
GENERATORS = $(sort $(dir $(wildcard $(GENERATOR_DIR)/*/.)))
|
||||
# Map this list of generator paths to "gen_{generator name}" entries
|
||||
|
@ -96,30 +96,30 @@ generate_tests: $(GENERATOR_TARGETS)
|
|||
|
||||
# "make pyspec" to create the pyspec for all phases.
|
||||
pyspec:
|
||||
. venv/bin/activate; python3 setup.py pyspecdev
|
||||
python3 -m venv venv; . venv/bin/activate; python3 setup.py pyspecdev
|
||||
|
||||
# installs the packages to run pyspec tests
|
||||
install_test:
|
||||
python3 -m venv venv; . venv/bin/activate; python3 -m pip install -e .[lint]; python3 -m pip install -e .[test]
|
||||
|
||||
# Testing against `minimal` config by default
|
||||
# Testing against `minimal` or `mainnet` config by default
|
||||
test: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.minimal --cov=eth2spec.altair.minimal --cov=eth2spec.bellatrix.minimal --cov=eth2spec.capella.minimal --cov=eth2spec.eip4844.minimal --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
python3 -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.$(TEST_PRESET_TYPE) --cov=eth2spec.altair.$(TEST_PRESET_TYPE) --cov=eth2spec.bellatrix.$(TEST_PRESET_TYPE) --cov=eth2spec.capella.$(TEST_PRESET_TYPE) --cov=eth2spec.eip4844.$(TEST_PRESET_TYPE) --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
|
||||
# Testing against `minimal` config by default
|
||||
# Testing against `minimal` or `mainnet` config by default
|
||||
find_test: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.minimal --cov=eth2spec.altair.minimal --cov=eth2spec.bellatrix.minimal --cov=eth2spec.capella.minimal --cov=eth2spec.eip4844.minimal --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
python3 -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.$(TEST_PRESET_TYPE) --cov=eth2spec.altair.$(TEST_PRESET_TYPE) --cov=eth2spec.bellatrix.$(TEST_PRESET_TYPE) --cov=eth2spec.capella.$(TEST_PRESET_TYPE) --cov=eth2spec.eip4844.$(TEST_PRESET_TYPE) --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
|
||||
citest: pyspec
|
||||
mkdir -p $(TEST_REPORT_DIR);
|
||||
ifdef fork
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -n 4 --bls-type=milagro --fork=$(fork) --junitxml=test-reports/test_results.xml eth2spec
|
||||
python3 -m pytest -n 16 --bls-type=milagro --preset=$(TEST_PRESET_TYPE) --fork=$(fork) --junitxml=test-reports/test_results.xml eth2spec
|
||||
else
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -n 4 --bls-type=milagro --junitxml=test-reports/test_results.xml eth2spec
|
||||
python3 -m pytest -n 16 --bls-type=milagro --preset=$(TEST_PRESET_TYPE) --junitxml=test-reports/test_results.xml eth2spec
|
||||
endif
|
||||
|
||||
|
||||
|
@ -135,7 +135,7 @@ check_toc: $(MARKDOWN_FILES:=.toc)
|
|||
rm $*.tmp
|
||||
|
||||
codespell:
|
||||
codespell . --skip ./.git -I .codespell-whitelist
|
||||
codespell . --skip "./.git,./venv,$(PY_SPEC_DIR)/.mypy_cache" -I .codespell-whitelist
|
||||
|
||||
# TODO: add future protocol upgrade patch packages to linting.
|
||||
# NOTE: we use `pylint` just for catching unused arguments in spec code
|
||||
|
|
|
@ -25,7 +25,7 @@ Features are researched and developed in parallel, and then consolidated into se
|
|||
| Code Name or Topic | Specs | Notes |
|
||||
| - | - | - |
|
||||
| Capella (tentative) | <ul><li>Core</li><ul><li>[Beacon chain changes](specs/capella/beacon-chain.md)</li><li>[Capella fork](specs/capella/fork.md)</li></ul><li>Additions</li><ul><li>[Validator additions](specs/capella/validator.md)</li><li>[P2P networking](specs/capella/p2p-interface.md)</li></ul></ul> |
|
||||
| EIP4844 (tentative) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/eip4844/beacon-chain.md)</li><li>[EIP-4844 fork](specs/eip4844/fork.md)</li><li>[Polynomial commitments](specs/eip4844/polynomial-commitments.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/eip4844/validator.md)</li><li>[P2P networking](specs/eip4844/p2p-interface.md)</li></ul></ul> |
|
||||
| EIP4844 (tentative) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/eip4844/beacon-chain.md)</li><li>[EIP-4844 fork](specs/eip4844/fork.md)</li><li>[Polynomial commitments](specs/eip4844/polynomial-commitments.md)</li><li>[Fork choice changes](specs/eip4844/fork-choice.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/eip4844/validator.md)</li><li>[P2P networking](specs/eip4844/p2p-interface.md)</li></ul></ul> |
|
||||
| Sharding (outdated) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/sharding/beacon-chain.md)</li></ul><li>Additions</li><ul><li>[P2P networking](specs/sharding/p2p-interface.md)</li></ul></ul> |
|
||||
| Custody Game (outdated) | <ul><li>Core</li><ul><li>[Beacon Chain changes](specs/custody_game/beacon-chain.md)</li></ul><li>Additions</li><ul><li>[Honest validator guide changes](specs/custody_game/validator.md)</li></ul></ul> | Dependent on sharding |
|
||||
| Data Availability Sampling (outdated) | <ul><li>Core</li><ul><li>[Core types and functions](specs/das/das-core.md)</li><li>[Fork choice changes](specs/das/fork-choice.md)</li></ul><li>Additions</li><ul><li>[P2P Networking](specs/das/p2p-interface.md)</li><li>[Sampling process](specs/das/sampling.md)</li></ul></ul> | <ul><li> Dependent on sharding</li><li>[Technical explainer](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/B1YJPGkpD)</li></ul> |
|
||||
|
|
29
setup.py
29
setup.py
|
@ -638,34 +638,6 @@ T = TypeVar('T') # For generic function
|
|||
@classmethod
|
||||
def sundry_functions(cls) -> str:
|
||||
return super().sundry_functions() + '\n\n' + '''
|
||||
#
|
||||
# Temporarily disable Withdrawals functions for EIP4844 testnets
|
||||
#
|
||||
|
||||
|
||||
def no_op(fn): # type: ignore
|
||||
# pylint: disable=unused-argument
|
||||
def wrapper(*args, **kw): # type: ignore
|
||||
return None
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_empty_list_result(fn): # type: ignore
|
||||
# pylint: disable=unused-argument
|
||||
def wrapper(*args, **kw): # type: ignore
|
||||
return []
|
||||
return wrapper
|
||||
|
||||
|
||||
process_withdrawals = no_op(process_withdrawals)
|
||||
process_bls_to_execution_change = no_op(process_bls_to_execution_change)
|
||||
get_expected_withdrawals = get_empty_list_result(get_expected_withdrawals)
|
||||
|
||||
|
||||
#
|
||||
# End
|
||||
#
|
||||
|
||||
def retrieve_blobs_sidecar(slot: Slot, beacon_block_root: Root) -> PyUnion[BlobsSidecar, str]:
|
||||
# pylint: disable=unused-argument
|
||||
return "TEST"'''
|
||||
|
@ -1020,6 +992,7 @@ class PySpecCommand(Command):
|
|||
self.md_doc_paths += """
|
||||
specs/eip4844/beacon-chain.md
|
||||
specs/eip4844/fork.md
|
||||
specs/eip4844/fork-choice.md
|
||||
specs/eip4844/polynomial-commitments.md
|
||||
specs/eip4844/p2p-interface.md
|
||||
specs/eip4844/validator.md
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
- [Introduction](#introduction)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [`compute_merkle_proof_for_state`](#compute_merkle_proof_for_state)
|
||||
- [`block_to_light_client_header`](#block_to_light_client_header)
|
||||
- [Deriving light client data](#deriving-light-client-data)
|
||||
- [`create_light_client_bootstrap`](#create_light_client_bootstrap)
|
||||
- [`create_light_client_update`](#create_light_client_update)
|
||||
|
@ -34,6 +35,19 @@ def compute_merkle_proof_for_state(state: BeaconState,
|
|||
...
|
||||
```
|
||||
|
||||
### `block_to_light_client_header`
|
||||
|
||||
```python
|
||||
def block_to_light_client_header(block: SignedBeaconBlock) -> BeaconBlockHeader:
|
||||
return BeaconBlockHeader(
|
||||
slot=block.message.slot,
|
||||
proposer_index=block.message.proposer_index,
|
||||
parent_root=block.message.parent_root,
|
||||
state_root=block.message.state_root,
|
||||
body_root=hash_tree_root(block.message.body),
|
||||
)
|
||||
```
|
||||
|
||||
## Deriving light client data
|
||||
|
||||
Full nodes are expected to derive light client data from historic blocks and states and provide it to other clients.
|
||||
|
@ -55,13 +69,7 @@ def create_light_client_bootstrap(state: BeaconState,
|
|||
assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||
|
||||
return LightClientBootstrap(
|
||||
header=BeaconBlockHeader(
|
||||
slot=state.latest_block_header.slot,
|
||||
proposer_index=state.latest_block_header.proposer_index,
|
||||
parent_root=state.latest_block_header.parent_root,
|
||||
state_root=hash_tree_root(state),
|
||||
body_root=state.latest_block_header.body_root,
|
||||
),
|
||||
header=block_to_light_client_header(block),
|
||||
current_sync_committee=state.current_sync_committee,
|
||||
current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX),
|
||||
)
|
||||
|
@ -103,42 +111,30 @@ def create_light_client_update(state: BeaconState,
|
|||
assert hash_tree_root(attested_header) == hash_tree_root(attested_block.message) == block.message.parent_root
|
||||
update_attested_period = compute_sync_committee_period_at_slot(attested_block.message.slot)
|
||||
|
||||
update = LightClientUpdate()
|
||||
|
||||
update.attested_header = block_to_light_client_header(attested_block)
|
||||
|
||||
# `next_sync_committee` is only useful if the message is signed by the current sync committee
|
||||
if update_attested_period == update_signature_period:
|
||||
next_sync_committee = attested_state.next_sync_committee
|
||||
next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
|
||||
else:
|
||||
next_sync_committee = SyncCommittee()
|
||||
next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
update.next_sync_committee = attested_state.next_sync_committee
|
||||
update.next_sync_committee_branch = compute_merkle_proof_for_state(
|
||||
attested_state, NEXT_SYNC_COMMITTEE_INDEX)
|
||||
|
||||
# Indicate finality whenever possible
|
||||
if finalized_block is not None:
|
||||
if finalized_block.message.slot != GENESIS_SLOT:
|
||||
finalized_header = BeaconBlockHeader(
|
||||
slot=finalized_block.message.slot,
|
||||
proposer_index=finalized_block.message.proposer_index,
|
||||
parent_root=finalized_block.message.parent_root,
|
||||
state_root=finalized_block.message.state_root,
|
||||
body_root=hash_tree_root(finalized_block.message.body),
|
||||
)
|
||||
assert hash_tree_root(finalized_header) == attested_state.finalized_checkpoint.root
|
||||
update.finalized_header = block_to_light_client_header(finalized_block)
|
||||
assert hash_tree_root(update.finalized_header) == attested_state.finalized_checkpoint.root
|
||||
else:
|
||||
assert attested_state.finalized_checkpoint.root == Bytes32()
|
||||
finalized_header = BeaconBlockHeader()
|
||||
finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
|
||||
else:
|
||||
finalized_header = BeaconBlockHeader()
|
||||
finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))]
|
||||
update.finality_branch = compute_merkle_proof_for_state(
|
||||
attested_state, FINALIZED_ROOT_INDEX)
|
||||
|
||||
return LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=block.message.body.sync_aggregate,
|
||||
signature_slot=block.message.slot,
|
||||
)
|
||||
update.sync_aggregate = block.message.body.sync_aggregate
|
||||
update.signature_slot = block.message.slot
|
||||
|
||||
return update
|
||||
```
|
||||
|
||||
Full nodes SHOULD provide the best derivable `LightClientUpdate` (according to `is_better_update`) for each sync committee period covering any epochs in range `[max(ALTAIR_FORK_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOCK_REQUESTS), current_epoch]` where `current_epoch` is defined by the current wall-clock time. Full nodes MAY also provide `LightClientUpdate` for other sync committee periods.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
- [`Withdrawal`](#withdrawal)
|
||||
- [`BLSToExecutionChange`](#blstoexecutionchange)
|
||||
- [`SignedBLSToExecutionChange`](#signedblstoexecutionchange)
|
||||
- [`HistoricalSummary`](#historicalsummary)
|
||||
- [Extended Containers](#extended-containers)
|
||||
- [`ExecutionPayload`](#executionpayload)
|
||||
- [`ExecutionPayloadHeader`](#executionpayloadheader)
|
||||
|
@ -29,6 +30,8 @@
|
|||
- [`is_fully_withdrawable_validator`](#is_fully_withdrawable_validator)
|
||||
- [`is_partially_withdrawable_validator`](#is_partially_withdrawable_validator)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Epoch processing](#epoch-processing)
|
||||
- [Historical summaries updates](#historical-summaries-updates)
|
||||
- [Block processing](#block-processing)
|
||||
- [New `get_expected_withdrawals`](#new-get_expected_withdrawals)
|
||||
- [New `process_withdrawals`](#new-process_withdrawals)
|
||||
|
@ -50,6 +53,11 @@ to validator withdrawals. Including:
|
|||
* Operation to change from `BLS_WITHDRAWAL_PREFIX` to
|
||||
`ETH1_ADDRESS_WITHDRAWAL_PREFIX` versioned withdrawal credentials to enable withdrawals for a validator.
|
||||
|
||||
Another new feature is the new independent state and block historical accumulators
|
||||
that replace the original singular historical roots. With these accumulators, it becomes possible to validate
|
||||
the entire block history that led up to that particular state without any additional information
|
||||
beyond the state and the blocks.
|
||||
|
||||
## Custom types
|
||||
|
||||
We define the following Python custom types for type hinting and readability:
|
||||
|
@ -115,6 +123,18 @@ class SignedBLSToExecutionChange(Container):
|
|||
signature: BLSSignature
|
||||
```
|
||||
|
||||
#### `HistoricalSummary`
|
||||
|
||||
```python
|
||||
class HistoricalSummary(Container):
|
||||
"""
|
||||
`HistoricalSummary` matches the components of the phase0 `HistoricalBatch`
|
||||
making the two hash_tree_root-compatible.
|
||||
"""
|
||||
block_summary_root: Root
|
||||
state_summary_root: Root
|
||||
```
|
||||
|
||||
### Extended Containers
|
||||
|
||||
#### `ExecutionPayload`
|
||||
|
@ -196,7 +216,7 @@ class BeaconState(Container):
|
|||
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]
|
||||
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT] # Frozen in Capella, replaced by historical_summaries
|
||||
# Eth1
|
||||
eth1_data: Eth1Data
|
||||
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
|
||||
|
@ -226,6 +246,8 @@ class BeaconState(Container):
|
|||
# Withdrawals
|
||||
next_withdrawal_index: WithdrawalIndex # [New in Capella]
|
||||
next_withdrawal_validator_index: ValidatorIndex # [New in Capella]
|
||||
# Deep history valid from Capella onwards
|
||||
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT] # [New in Capella]
|
||||
```
|
||||
|
||||
## Helpers
|
||||
|
@ -270,6 +292,40 @@ def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) ->
|
|||
|
||||
## Beacon chain state transition function
|
||||
|
||||
### Epoch processing
|
||||
|
||||
*Note*: The function `process_historical_summaries_update` replaces `process_historical_roots_update` in Bellatrix.
|
||||
|
||||
```python
|
||||
def process_epoch(state: BeaconState) -> None:
|
||||
process_justification_and_finalization(state)
|
||||
process_inactivity_updates(state)
|
||||
process_rewards_and_penalties(state)
|
||||
process_registry_updates(state)
|
||||
process_slashings(state)
|
||||
process_eth1_data_reset(state)
|
||||
process_effective_balance_updates(state)
|
||||
process_slashings_reset(state)
|
||||
process_randao_mixes_reset(state)
|
||||
process_historical_summaries_update(state) # [Modified in Capella]
|
||||
process_participation_flag_updates(state)
|
||||
process_sync_committee_updates(state)
|
||||
```
|
||||
|
||||
#### Historical summaries updates
|
||||
|
||||
```python
|
||||
def process_historical_summaries_update(state: BeaconState) -> None:
|
||||
# Set historical block root accumulator.
|
||||
next_epoch = Epoch(get_current_epoch(state) + 1)
|
||||
if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
|
||||
historical_summary = HistoricalSummary(
|
||||
block_summary_root=hash_tree_root(state.block_roots),
|
||||
state_summary_root=hash_tree_root(state.state_roots),
|
||||
)
|
||||
state.historical_summaries.append(historical_summary)
|
||||
```
|
||||
|
||||
### Block processing
|
||||
|
||||
```python
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
- [`ExecutionPayloadHeader`](#executionpayloadheader)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [`validate_blobs_sidecar`](#validate_blobs_sidecar)
|
||||
- [`is_data_available`](#is_data_available)
|
||||
- [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash)
|
||||
- [`tx_peek_blob_versioned_hashes`](#tx_peek_blob_versioned_hashes)
|
||||
- [`verify_kzg_commitments_against_transactions`](#verify_kzg_commitments_against_transactions)
|
||||
|
@ -33,7 +31,6 @@
|
|||
- [`process_execution_payload`](#process_execution_payload)
|
||||
- [Blob KZG commitments](#blob-kzg-commitments)
|
||||
- [Testing](#testing)
|
||||
- [Disabling Withdrawals](#disabling-withdrawals)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
@ -146,45 +143,6 @@ class ExecutionPayloadHeader(Container):
|
|||
|
||||
### Misc
|
||||
|
||||
#### `validate_blobs_sidecar`
|
||||
|
||||
```python
|
||||
def validate_blobs_sidecar(slot: Slot,
|
||||
beacon_block_root: Root,
|
||||
expected_kzg_commitments: Sequence[KZGCommitment],
|
||||
blobs_sidecar: BlobsSidecar) -> None:
|
||||
assert slot == blobs_sidecar.beacon_block_slot
|
||||
assert beacon_block_root == blobs_sidecar.beacon_block_root
|
||||
blobs = blobs_sidecar.blobs
|
||||
kzg_aggregated_proof = blobs_sidecar.kzg_aggregated_proof
|
||||
assert len(expected_kzg_commitments) == len(blobs)
|
||||
|
||||
assert verify_aggregate_kzg_proof(blobs, expected_kzg_commitments, kzg_aggregated_proof)
|
||||
```
|
||||
|
||||
#### `is_data_available`
|
||||
|
||||
The implementation of `is_data_available` is meant to change with later sharding upgrades.
|
||||
Initially, it requires every verifying actor to retrieve the matching `BlobsSidecar`,
|
||||
and validate the sidecar with `validate_blobs_sidecar`.
|
||||
|
||||
The block MUST NOT be considered valid until a valid `BlobsSidecar` has been downloaded.
|
||||
|
||||
```python
|
||||
def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: Sequence[KZGCommitment]) -> bool:
|
||||
# `retrieve_blobs_sidecar` is implementation dependent, raises an exception if not available.
|
||||
sidecar = retrieve_blobs_sidecar(slot, beacon_block_root)
|
||||
|
||||
# For testing, `retrieve_blobs_sidecar` returns "TEST".
|
||||
# TODO: Remove it once we have a way to inject `BlobsSidecar` into tests.
|
||||
if isinstance(sidecar, str):
|
||||
return True
|
||||
|
||||
validate_blobs_sidecar(slot, beacon_block_root, blob_kzg_commitments, sidecar)
|
||||
return True
|
||||
```
|
||||
|
||||
|
||||
#### `kzg_commitment_to_versioned_hash`
|
||||
|
||||
```python
|
||||
|
@ -240,9 +198,6 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
process_operations(state, block.body)
|
||||
process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
process_blob_kzg_commitments(state, block.body) # [New in EIP-4844]
|
||||
|
||||
# New in EIP-4844
|
||||
assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments)
|
||||
```
|
||||
|
||||
#### Execution payload
|
||||
|
@ -345,11 +300,3 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
|
|||
|
||||
return state
|
||||
```
|
||||
|
||||
### Disabling Withdrawals
|
||||
|
||||
During testing we avoid Capella-specific updates to the state transition. We do this by replacing the following functions with a no-op implementation:
|
||||
- `process_withdrawals`
|
||||
- `process_bls_to_execution_change`
|
||||
|
||||
The `get_expected_withdrawals` function is also modified to return an empty withdrawals list. As such, the `PayloadAttributes` used to update forkchoice does not contain withdrawals.
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
# EIP-4844 -- Fork Choice
|
||||
|
||||
## 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)
|
||||
- [Containers](#containers)
|
||||
- [`BlobsSidecar`](#blobssidecar)
|
||||
- [Helpers](#helpers)
|
||||
- [`validate_blobs_sidecar`](#validate_blobs_sidecar)
|
||||
- [`is_data_available`](#is_data_available)
|
||||
- [Updated fork-choice handlers](#updated-fork-choice-handlers)
|
||||
- [`on_block`](#on_block)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This is the modification of the fork choice accompanying the EIP-4844 upgrade.
|
||||
|
||||
## Containers
|
||||
|
||||
### `BlobsSidecar`
|
||||
|
||||
```python
|
||||
class BlobsSidecar(Container):
|
||||
beacon_block_root: Root
|
||||
beacon_block_slot: Slot
|
||||
blobs: List[Blob, MAX_BLOBS_PER_BLOCK]
|
||||
kzg_aggregated_proof: KZGProof
|
||||
```
|
||||
|
||||
## Helpers
|
||||
|
||||
#### `validate_blobs_sidecar`
|
||||
|
||||
```python
|
||||
def validate_blobs_sidecar(slot: Slot,
|
||||
beacon_block_root: Root,
|
||||
expected_kzg_commitments: Sequence[KZGCommitment],
|
||||
blobs_sidecar: BlobsSidecar) -> None:
|
||||
assert slot == blobs_sidecar.beacon_block_slot
|
||||
assert beacon_block_root == blobs_sidecar.beacon_block_root
|
||||
blobs = blobs_sidecar.blobs
|
||||
kzg_aggregated_proof = blobs_sidecar.kzg_aggregated_proof
|
||||
assert len(expected_kzg_commitments) == len(blobs)
|
||||
|
||||
assert verify_aggregate_kzg_proof(blobs, expected_kzg_commitments, kzg_aggregated_proof)
|
||||
```
|
||||
|
||||
#### `is_data_available`
|
||||
|
||||
The implementation of `is_data_available` will become more sophisticated during later scaling upgrades.
|
||||
Initially, verification requires every verifying actor to retrieve the matching `BlobsSidecar`,
|
||||
and validate the sidecar with `validate_blobs_sidecar`.
|
||||
|
||||
The block MUST NOT be considered valid until a valid `BlobsSidecar` has been downloaded. Blocks that have been previously validated as available SHOULD be considered available even if the associated `BlobsSidecar` has subsequently been pruned.
|
||||
|
||||
```python
|
||||
def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: Sequence[KZGCommitment]) -> bool:
|
||||
# `retrieve_blobs_sidecar` is implementation and context dependent, raises an exception if not available.
|
||||
# Note: the p2p network does not guarantee sidecar retrieval outside of `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS`
|
||||
sidecar = retrieve_blobs_sidecar(slot, beacon_block_root)
|
||||
|
||||
# For testing, `retrieve_blobs_sidecar` returns "TEST".
|
||||
# TODO: Remove it once we have a way to inject `BlobsSidecar` into tests.
|
||||
if isinstance(sidecar, str):
|
||||
return True
|
||||
|
||||
validate_blobs_sidecar(slot, beacon_block_root, blob_kzg_commitments, sidecar)
|
||||
return True
|
||||
```
|
||||
|
||||
## Updated fork-choice handlers
|
||||
|
||||
### `on_block`
|
||||
|
||||
*Note*: The only modification is the addition of the verification of transition block conditions.
|
||||
|
||||
```python
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
"""
|
||||
block = signed_block.message
|
||||
# Parent block must be known
|
||||
assert block.parent_root in store.block_states
|
||||
# Make a copy of the state to avoid mutability issues
|
||||
pre_state = copy(store.block_states[block.parent_root])
|
||||
# Blocks cannot be in the future. If they are, their consideration must be delayed until they are in the past.
|
||||
assert get_current_slot(store) >= block.slot
|
||||
|
||||
# Check that block is later than the finalized epoch slot (optimization to reduce calls to get_ancestor)
|
||||
finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)
|
||||
assert block.slot > finalized_slot
|
||||
# Check block is a descendant of the finalized block at the checkpoint finalized slot
|
||||
assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root
|
||||
|
||||
# [New in EIP-4844]
|
||||
# Check if blob data is available
|
||||
# If not, this block MAY be queued and subsequently considered when blob data becomes available
|
||||
assert is_data_available(block.slot, hash_tree_root(block), block.body.blob_kzg_commitments)
|
||||
|
||||
# Check the block is valid and compute the post-state
|
||||
state = pre_state.copy()
|
||||
state_transition(state, signed_block, True)
|
||||
|
||||
# Check the merge transition
|
||||
if is_merge_transition_block(pre_state, block.body):
|
||||
validate_merge_block(block)
|
||||
|
||||
# Add new block to the store
|
||||
store.blocks[hash_tree_root(block)] = block
|
||||
# Add new state for this block to the store
|
||||
store.block_states[hash_tree_root(block)] = state
|
||||
|
||||
# Add proposer score boost if the block is timely
|
||||
time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT
|
||||
is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT
|
||||
if get_current_slot(store) == block.slot and is_before_attesting_interval:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
|
||||
# Update justified checkpoint
|
||||
if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
|
||||
if state.current_justified_checkpoint.epoch > store.best_justified_checkpoint.epoch:
|
||||
store.best_justified_checkpoint = state.current_justified_checkpoint
|
||||
if should_update_justified_checkpoint(store, state.current_justified_checkpoint):
|
||||
store.justified_checkpoint = state.current_justified_checkpoint
|
||||
|
||||
# Update finalized checkpoint
|
||||
if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch:
|
||||
store.finalized_checkpoint = state.finalized_checkpoint
|
||||
store.justified_checkpoint = state.current_justified_checkpoint
|
||||
```
|
|
@ -12,7 +12,6 @@ The specification of these changes continues in the same format as the network s
|
|||
|
||||
- [Configuration](#configuration)
|
||||
- [Containers](#containers)
|
||||
- [`BlobsSidecar`](#blobssidecar)
|
||||
- [`SignedBeaconBlockAndBlobsSidecar`](#signedbeaconblockandblobssidecar)
|
||||
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
|
||||
- [Topics and messages](#topics-and-messages)
|
||||
|
@ -41,16 +40,6 @@ The specification of these changes continues in the same format as the network s
|
|||
|
||||
## Containers
|
||||
|
||||
### `BlobsSidecar`
|
||||
|
||||
```python
|
||||
class BlobsSidecar(Container):
|
||||
beacon_block_root: Root
|
||||
beacon_block_slot: Slot
|
||||
blobs: List[Blob, MAX_BLOBS_PER_BLOCK]
|
||||
kzg_aggregated_proof: KZGProof
|
||||
```
|
||||
|
||||
### `SignedBeaconBlockAndBlobsSidecar`
|
||||
|
||||
```python
|
||||
|
@ -141,8 +130,8 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
|
|||
|
||||
**Protocol ID:** `/eth2/beacon_chain/req/beacon_blocks_by_root/2/`
|
||||
|
||||
After `EIP4844_FORK_EPOCH`, `BeaconBlocksByRootV2` is replaced by `BeaconBlockAndBlobsSidecarByRootV1`
|
||||
clients MUST support requesting blocks by root for pre-fork-epoch blocks.
|
||||
After `EIP4844_FORK_EPOCH`, `BeaconBlocksByRootV2` is replaced by `BeaconBlockAndBlobsSidecarByRootV1`.
|
||||
Clients MUST support requesting blocks by root for pre-fork-epoch blocks.
|
||||
|
||||
Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
|
||||
|
||||
|
@ -186,7 +175,7 @@ No more than `MAX_REQUEST_BLOCKS` may be requested at a time.
|
|||
The response MUST consist of zero or more `response_chunk`.
|
||||
Each _successful_ `response_chunk` MUST contain a single `SignedBeaconBlockAndBlobsSidecar` payload.
|
||||
|
||||
Clients MUST support requesting blocks and sidecars since the latest finalized epoch.
|
||||
Clients MUST support requesting blocks and sidecars since `minimum_request_epoch`, where `minimum_request_epoch = max(finalized_epoch, current_epoch - MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS, EIP4844_FORK_EPOCH)`. If any root in the request content references a block earlier than `minimum_request_epoch`, peers SHOULD respond with error code `3: ResourceUnavailable`.
|
||||
|
||||
Clients MUST respond with at least one block and sidecar, if they have it.
|
||||
Clients MAY limit the number of blocks and sidecars in the response.
|
||||
|
@ -219,7 +208,7 @@ may not be available beyond the initial distribution via gossip.
|
|||
Before consuming the next response chunk, the response reader SHOULD verify the blobs sidecar is well-formatted and
|
||||
correct w.r.t. the expected KZG commitments through `validate_blobs_sidecar`.
|
||||
|
||||
`BlobsSidecarsByRange` is primarily used to sync blobs that may have been missed on gossip.
|
||||
`BlobsSidecarsByRange` is primarily used to sync blobs that may have been missed on gossip and to sync within the `MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS` window.
|
||||
|
||||
The request MUST be encoded as an SSZ-container.
|
||||
|
||||
|
@ -227,7 +216,7 @@ The response MUST consist of zero or more `response_chunk`.
|
|||
Each _successful_ `response_chunk` MUST contain a single `BlobsSidecar` payload.
|
||||
|
||||
Clients MUST keep a record of signed blobs sidecars seen on the epoch range
|
||||
`[max(GENESIS_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS), current_epoch]`
|
||||
`[max(current_epoch - MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS, EIP4844_FORK_EPOCH), current_epoch]`
|
||||
where `current_epoch` is defined by the current wall-clock time,
|
||||
and clients MUST support serving requests of blocks on this range.
|
||||
|
||||
|
|
|
@ -370,8 +370,9 @@ def verify_kzg_proof_impl(polynomial_kzg: KZGCommitment,
|
|||
```python
|
||||
def compute_kzg_proof(polynomial: Polynomial, z: BLSFieldElement) -> KZGProof:
|
||||
"""
|
||||
Compute KZG proof at point `z` with `polynomial` being in evaluation form
|
||||
Do this by computing the quotient polynomial in evaluation form: q(x) = (p(x) - p(z)) / (x - z)
|
||||
Compute KZG proof at point `z` with `polynomial` being in evaluation form.
|
||||
Do this by computing the quotient polynomial in evaluation form: q(x) = (p(x) - p(z)) / (x - z).
|
||||
Public method.
|
||||
"""
|
||||
y = evaluate_polynomial_in_evaluation_form(polynomial, z)
|
||||
polynomial_shifted = [BLSFieldElement((int(p) - int(y)) % BLS_MODULUS) for p in polynomial]
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.3.0-alpha.2
|
||||
1.3.0-rc.0
|
||||
|
|
|
@ -10,8 +10,8 @@ from eth2spec.test.context import (
|
|||
@spec_state_test
|
||||
def test_current_sync_committee_merkle_proof(spec, state):
|
||||
yield "object", state
|
||||
current_sync_committee_branch = \
|
||||
spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX)
|
||||
current_sync_committee_branch = spec.compute_merkle_proof_for_state(
|
||||
state, spec.CURRENT_SYNC_COMMITTEE_INDEX)
|
||||
yield "proof", {
|
||||
"leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(),
|
||||
"leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX,
|
||||
|
@ -31,8 +31,8 @@ def test_current_sync_committee_merkle_proof(spec, state):
|
|||
@spec_state_test
|
||||
def test_next_sync_committee_merkle_proof(spec, state):
|
||||
yield "object", state
|
||||
next_sync_committee_branch = \
|
||||
spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||
next_sync_committee_branch = spec.compute_merkle_proof_for_state(
|
||||
state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||
yield "proof", {
|
||||
"leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(),
|
||||
"leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX,
|
||||
|
@ -52,8 +52,8 @@ def test_next_sync_committee_merkle_proof(spec, state):
|
|||
@spec_state_test
|
||||
def test_finality_root_merkle_proof(spec, state):
|
||||
yield "object", state
|
||||
finality_branch = \
|
||||
spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX)
|
||||
finality_branch = spec.compute_merkle_proof_for_state(
|
||||
state, spec.FINALIZED_ROOT_INDEX)
|
||||
yield "proof", {
|
||||
"leaf": "0x" + state.finalized_checkpoint.root.hex(),
|
||||
"leaf_index": spec.FINALIZED_ROOT_INDEX,
|
||||
|
|
|
@ -9,45 +9,23 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.helpers.light_client import (
|
||||
get_sync_aggregate,
|
||||
signed_block_to_header,
|
||||
create_update,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_slots,
|
||||
)
|
||||
from math import floor
|
||||
|
||||
|
||||
def create_update(spec, test, with_next, with_finality, participation_rate):
|
||||
def create_test_update(spec, test, with_next, with_finality, participation_rate):
|
||||
attested_state, attested_block, finalized_block = test
|
||||
num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate)
|
||||
|
||||
attested_header = signed_block_to_header(spec, attested_block)
|
||||
|
||||
if with_next:
|
||||
next_sync_committee = attested_state.next_sync_committee
|
||||
next_sync_committee_branch = spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||
else:
|
||||
next_sync_committee = spec.SyncCommittee()
|
||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
|
||||
if with_finality:
|
||||
finalized_header = signed_block_to_header(spec, finalized_block)
|
||||
finality_branch = spec.compute_merkle_proof_for_state(attested_state, spec.FINALIZED_ROOT_INDEX)
|
||||
else:
|
||||
finalized_header = spec.BeaconBlockHeader()
|
||||
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
|
||||
|
||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, attested_state, num_participants)
|
||||
|
||||
return spec.LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=sync_aggregate,
|
||||
signature_slot=signature_slot,
|
||||
return create_update(
|
||||
spec,
|
||||
attested_state,
|
||||
attested_block,
|
||||
finalized_block,
|
||||
with_next,
|
||||
with_finality,
|
||||
participation_rate,
|
||||
)
|
||||
|
||||
|
||||
|
@ -84,76 +62,76 @@ def test_update_ranking(spec, state):
|
|||
# Create updates (in descending order of quality)
|
||||
updates = [
|
||||
# Updates with sync committee finality
|
||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
|
||||
# Updates without sync committee finality
|
||||
create_update(spec, att, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.8),
|
||||
|
||||
# Updates without indication of any finality
|
||||
create_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.8),
|
||||
|
||||
# Updates with sync committee finality but no `next_sync_committee`
|
||||
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
|
||||
# Updates without sync committee finality and also no `next_sync_committee`
|
||||
create_update(spec, att, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=1.0),
|
||||
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.8),
|
||||
|
||||
# Updates without indication of any finality nor `next_sync_committee`
|
||||
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, att, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=1.0),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.8),
|
||||
|
||||
# Updates with low sync committee participation
|
||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.4),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.4),
|
||||
|
||||
# Updates with very low sync committee participation
|
||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.2),
|
||||
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.2),
|
||||
]
|
||||
yield "updates", updates
|
||||
|
||||
|
|
|
@ -11,43 +11,44 @@ from eth2spec.test.helpers.attestations import (
|
|||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
from eth2spec.test.helpers.light_client import (
|
||||
get_sync_aggregate,
|
||||
initialize_light_client_store,
|
||||
signed_block_to_header,
|
||||
create_update,
|
||||
)
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_slots,
|
||||
)
|
||||
|
||||
|
||||
def setup_test(spec, state):
|
||||
trusted_block = spec.SignedBeaconBlock()
|
||||
trusted_block.message.state_root = state.hash_tree_root()
|
||||
trusted_block_root = trusted_block.message.hash_tree_root()
|
||||
bootstrap = spec.create_light_client_bootstrap(state, trusted_block)
|
||||
store = spec.initialize_light_client_store(trusted_block_root, bootstrap)
|
||||
store.next_sync_committee = state.next_sync_committee
|
||||
|
||||
return (trusted_block, store)
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@spec_state_test_with_matching_config
|
||||
def test_process_light_client_update_not_timeout(spec, state):
|
||||
store = initialize_light_client_store(spec, state)
|
||||
genesis_block, store = setup_test(spec, state)
|
||||
|
||||
# Block at slot 1 doesn't increase sync committee period, so it won't force update store.finalized_header
|
||||
attested_block = state_transition_with_full_block(spec, state, False, False)
|
||||
attested_header = signed_block_to_header(spec, attested_block)
|
||||
|
||||
# Sync committee signing the attested_header
|
||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
||||
next_sync_committee = spec.SyncCommittee()
|
||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
signature_slot = state.slot + 1
|
||||
|
||||
# Ensure that finality checkpoint is genesis
|
||||
assert state.finalized_checkpoint.epoch == 0
|
||||
# Finality is unchanged
|
||||
finalized_header = spec.BeaconBlockHeader()
|
||||
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
|
||||
|
||||
update = spec.LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=sync_aggregate,
|
||||
signature_slot=signature_slot,
|
||||
update = create_update(
|
||||
spec,
|
||||
attested_state=state,
|
||||
attested_block=attested_block,
|
||||
finalized_block=genesis_block,
|
||||
with_next=False,
|
||||
with_finality=False,
|
||||
participation_rate=1.0,
|
||||
)
|
||||
|
||||
pre_store = deepcopy(store)
|
||||
|
@ -64,7 +65,7 @@ def test_process_light_client_update_not_timeout(spec, state):
|
|||
@spec_state_test_with_matching_config
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_process_light_client_update_at_period_boundary(spec, state):
|
||||
store = initialize_light_client_store(spec, state)
|
||||
genesis_block, store = setup_test(spec, state)
|
||||
|
||||
# Forward to slot before next sync committee period so that next block is final one in period
|
||||
next_slots(spec, state, spec.UPDATE_TIMEOUT - 2)
|
||||
|
@ -73,25 +74,16 @@ def test_process_light_client_update_at_period_boundary(spec, state):
|
|||
assert store_period == update_period
|
||||
|
||||
attested_block = state_transition_with_full_block(spec, state, False, False)
|
||||
attested_header = signed_block_to_header(spec, attested_block)
|
||||
signature_slot = state.slot + 1
|
||||
|
||||
# Sync committee signing the attested_header
|
||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
||||
next_sync_committee = spec.SyncCommittee()
|
||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
|
||||
# Finality is unchanged
|
||||
finalized_header = spec.BeaconBlockHeader()
|
||||
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
|
||||
|
||||
update = spec.LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=sync_aggregate,
|
||||
signature_slot=signature_slot,
|
||||
update = create_update(
|
||||
spec,
|
||||
attested_state=state,
|
||||
attested_block=attested_block,
|
||||
finalized_block=genesis_block,
|
||||
with_next=False,
|
||||
with_finality=False,
|
||||
participation_rate=1.0,
|
||||
)
|
||||
|
||||
pre_store = deepcopy(store)
|
||||
|
@ -108,7 +100,7 @@ def test_process_light_client_update_at_period_boundary(spec, state):
|
|||
@spec_state_test_with_matching_config
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_process_light_client_update_timeout(spec, state):
|
||||
store = initialize_light_client_store(spec, state)
|
||||
genesis_block, store = setup_test(spec, state)
|
||||
|
||||
# Forward to next sync committee period
|
||||
next_slots(spec, state, spec.UPDATE_TIMEOUT)
|
||||
|
@ -117,26 +109,16 @@ def test_process_light_client_update_timeout(spec, state):
|
|||
assert store_period + 1 == update_period
|
||||
|
||||
attested_block = state_transition_with_full_block(spec, state, False, False)
|
||||
attested_header = signed_block_to_header(spec, attested_block)
|
||||
signature_slot = state.slot + 1
|
||||
|
||||
# Sync committee signing the attested_header
|
||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
||||
|
||||
# Sync committee is updated
|
||||
next_sync_committee = state.next_sync_committee
|
||||
next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||
# Finality is unchanged
|
||||
finalized_header = spec.BeaconBlockHeader()
|
||||
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
|
||||
|
||||
update = spec.LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=sync_aggregate,
|
||||
signature_slot=signature_slot,
|
||||
update = create_update(
|
||||
spec,
|
||||
attested_state=state,
|
||||
attested_block=attested_block,
|
||||
finalized_block=genesis_block,
|
||||
with_next=True,
|
||||
with_finality=False,
|
||||
participation_rate=1.0,
|
||||
)
|
||||
|
||||
pre_store = deepcopy(store)
|
||||
|
@ -153,7 +135,7 @@ def test_process_light_client_update_timeout(spec, state):
|
|||
@spec_state_test_with_matching_config
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_process_light_client_update_finality_updated(spec, state):
|
||||
store = initialize_light_client_store(spec, state)
|
||||
_, store = setup_test(spec, state)
|
||||
|
||||
# Change finality
|
||||
blocks = []
|
||||
|
@ -169,28 +151,21 @@ def test_process_light_client_update_finality_updated(spec, state):
|
|||
assert store_period == update_period
|
||||
|
||||
attested_block = blocks[-1]
|
||||
attested_header = signed_block_to_header(spec, attested_block)
|
||||
signature_slot = state.slot + 1
|
||||
|
||||
# Sync committee signing the attested_header
|
||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
||||
|
||||
# Updated sync_committee and finality
|
||||
next_sync_committee = spec.SyncCommittee()
|
||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
# Updated finality
|
||||
finalized_block = blocks[spec.SLOTS_PER_EPOCH - 1]
|
||||
finalized_header = signed_block_to_header(spec, finalized_block)
|
||||
assert finalized_header.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
|
||||
assert finalized_header.hash_tree_root() == state.finalized_checkpoint.root
|
||||
finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX)
|
||||
assert finalized_block.message.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
|
||||
assert finalized_block.message.hash_tree_root() == state.finalized_checkpoint.root
|
||||
|
||||
update = spec.LightClientUpdate(
|
||||
attested_header=attested_header,
|
||||
next_sync_committee=next_sync_committee,
|
||||
next_sync_committee_branch=next_sync_committee_branch,
|
||||
finalized_header=finalized_header,
|
||||
finality_branch=finality_branch,
|
||||
sync_aggregate=sync_aggregate,
|
||||
signature_slot=signature_slot,
|
||||
update = create_update(
|
||||
spec,
|
||||
attested_state=state,
|
||||
attested_block=attested_block,
|
||||
finalized_block=finalized_block,
|
||||
with_next=False,
|
||||
with_finality=True,
|
||||
participation_rate=1.0,
|
||||
)
|
||||
|
||||
spec.process_light_client_update(store, update, signature_slot, state.genesis_validators_root)
|
||||
|
|
|
@ -64,6 +64,7 @@ def test_from_syncing_to_invalid(spec, state):
|
|||
block.body.execution_payload.parent_hash = (
|
||||
block_hashes[f'chain_a_{i - 1}'] if i != 0 else block_hashes['block_0']
|
||||
)
|
||||
block.body.execution_payload.extra_data = spec.hash(bytes(f'chain_a_{i}', 'UTF-8'))
|
||||
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload)
|
||||
block_hashes[f'chain_a_{i}'] = block.body.execution_payload.block_hash
|
||||
|
||||
|
@ -80,6 +81,7 @@ def test_from_syncing_to_invalid(spec, state):
|
|||
block.body.execution_payload.parent_hash = (
|
||||
block_hashes[f'chain_b_{i - 1}'] if i != 0 else block_hashes['block_0']
|
||||
)
|
||||
block.body.execution_payload.extra_data = spec.hash(bytes(f'chain_b_{i}', 'UTF-8'))
|
||||
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload)
|
||||
block_hashes[f'chain_b_{i}'] = block.body.execution_payload.block_hash
|
||||
|
||||
|
@ -92,9 +94,13 @@ def test_from_syncing_to_invalid(spec, state):
|
|||
# Now add block 4 to chain `b` with INVALID
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.body.execution_payload.parent_hash = signed_blocks_b[-1].message.body.execution_payload.block_hash
|
||||
block.body.execution_payload.extra_data = spec.hash(bytes(f'chain_b_{i}', 'UTF-8'))
|
||||
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload)
|
||||
block_hashes['chain_b_3'] = block.body.execution_payload.block_hash
|
||||
|
||||
# Ensure that no duplicate block hashes
|
||||
assert len(block_hashes) == len(set(block_hashes.values()))
|
||||
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
payload_status = PayloadStatusV1(
|
||||
status=PayloadStatusV1Status.INVALID,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from eth2spec.test.helpers.constants import CAPELLA
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_phases, always_bls
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_capella_and_later, always_bls
|
||||
|
||||
|
||||
def run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=True):
|
||||
|
@ -38,14 +37,14 @@ def run_bls_to_execution_change_processing(spec, state, signed_address_change, v
|
|||
yield 'post', state
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success(spec, state):
|
||||
signed_address_change = get_signed_address_change(spec, state)
|
||||
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_not_activated(spec, state):
|
||||
validator_index = 3
|
||||
|
@ -63,7 +62,7 @@ def test_success_not_activated(spec, state):
|
|||
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_in_activation_queue(spec, state):
|
||||
validator_index = 3
|
||||
|
@ -81,7 +80,7 @@ def test_success_in_activation_queue(spec, state):
|
|||
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_in_exit_queue(spec, state):
|
||||
validator_index = 3
|
||||
|
@ -94,7 +93,7 @@ def test_success_in_exit_queue(spec, state):
|
|||
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_exited(spec, state):
|
||||
validator_index = 4
|
||||
|
@ -111,7 +110,7 @@ def test_success_exited(spec, state):
|
|||
assert not spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_withdrawable(spec, state):
|
||||
validator_index = 4
|
||||
|
@ -129,7 +128,7 @@ def test_success_withdrawable(spec, state):
|
|||
assert spec.is_fully_withdrawable_validator(validator, balance, spec.get_current_epoch(state))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_val_index_out_of_range(spec, state):
|
||||
# Create for one validator beyond the validator list length
|
||||
|
@ -138,7 +137,7 @@ def test_invalid_val_index_out_of_range(spec, state):
|
|||
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_already_0x01(spec, state):
|
||||
# Create for one validator beyond the validator list length
|
||||
|
@ -150,7 +149,7 @@ def test_invalid_already_0x01(spec, state):
|
|||
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_from_bls_pubkey(spec, state):
|
||||
# Create for one validator beyond the validator list length
|
||||
|
@ -164,7 +163,7 @@ def test_invalid_incorrect_from_bls_pubkey(spec, state):
|
|||
yield from run_bls_to_execution_change_processing(spec, state, signed_address_change, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_bad_signature(spec, state):
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_phases,
|
||||
with_capella_and_later,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import CAPELLA
|
||||
from eth2spec.test.helpers.state import next_epoch_via_block
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
prepare_state_and_deposit,
|
||||
|
@ -11,7 +10,7 @@ from eth2spec.test.helpers.deposits import (
|
|||
from eth2spec.test.helpers.withdrawals import set_validator_fully_withdrawable
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_top_up_to_withdrawn_validator(spec, state):
|
||||
validator_index = 0
|
||||
|
|
|
@ -4,9 +4,9 @@ from eth2spec.test.context import (
|
|||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
with_presets,
|
||||
with_phases,
|
||||
with_capella_and_later,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import MAINNET, MINIMAL, CAPELLA
|
||||
from eth2spec.test.helpers.constants import MAINNET, MINIMAL
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
build_empty_execution_payload,
|
||||
compute_el_block_hash,
|
||||
|
@ -97,7 +97,7 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with
|
|||
return expected_withdrawals
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_zero_expected_withdrawals(spec, state):
|
||||
assert len(spec.get_expected_withdrawals(state)) == 0
|
||||
|
@ -108,7 +108,7 @@ def test_success_zero_expected_withdrawals(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_full_withdrawal(spec, state):
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
|
@ -125,7 +125,7 @@ def test_success_one_full_withdrawal(spec, state):
|
|||
partial_withdrawals_indices=partial_withdrawals_indices)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawal(spec, state):
|
||||
fully_withdrawable_indices, partial_withdrawals_indices = prepare_expected_withdrawals(
|
||||
|
@ -145,7 +145,7 @@ def test_success_one_partial_withdrawal(spec, state):
|
|||
)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_max_per_slot(spec, state):
|
||||
num_full_withdrawals = spec.MAX_WITHDRAWALS_PER_PAYLOAD // 2
|
||||
|
@ -163,7 +163,7 @@ def test_success_max_per_slot(spec, state):
|
|||
partial_withdrawals_indices=partial_withdrawals_indices)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@with_presets([MAINNET], reason="too few validators with minimal config")
|
||||
@spec_state_test
|
||||
def test_success_all_fully_withdrawable_in_one_sweep(spec, state):
|
||||
|
@ -182,7 +182,7 @@ def test_success_all_fully_withdrawable_in_one_sweep(spec, state):
|
|||
partial_withdrawals_indices=partial_withdrawals_indices)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@with_presets([MINIMAL], reason="too many validators with mainnet config")
|
||||
@spec_state_test
|
||||
def test_success_all_fully_withdrawable(spec, state):
|
||||
|
@ -201,7 +201,7 @@ def test_success_all_fully_withdrawable(spec, state):
|
|||
partial_withdrawals_indices=partial_withdrawals_indices)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@with_presets([MAINNET], reason="too few validators with minimal config")
|
||||
@spec_state_test
|
||||
def test_success_all_partially_withdrawable_in_one_sweep(spec, state):
|
||||
|
@ -220,7 +220,7 @@ def test_success_all_partially_withdrawable_in_one_sweep(spec, state):
|
|||
partial_withdrawals_indices=partial_withdrawals_indices)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@with_presets([MINIMAL], reason="too many validators with mainnet config")
|
||||
@spec_state_test
|
||||
def test_success_all_partially_withdrawable(spec, state):
|
||||
|
@ -243,7 +243,7 @@ def test_success_all_partially_withdrawable(spec, state):
|
|||
# Failure cases in which the number of withdrawals in the execution_payload is incorrect
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_non_withdrawable_non_empty_withdrawals(spec, state):
|
||||
next_slot(spec, state)
|
||||
|
@ -260,7 +260,7 @@ def test_invalid_non_withdrawable_non_empty_withdrawals(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
|
||||
|
@ -273,7 +273,7 @@ def test_invalid_one_expected_full_withdrawal_and_none_in_withdrawals(spec, stat
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1)
|
||||
|
@ -286,7 +286,7 @@ def test_invalid_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, s
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=2)
|
||||
|
@ -299,7 +299,7 @@ def test_invalid_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec,
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=2)
|
||||
|
@ -312,7 +312,7 @@ def test_invalid_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(sp
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
|
||||
|
@ -325,7 +325,7 @@ def test_invalid_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec,
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
|
||||
|
@ -338,7 +338,7 @@ def test_invalid_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(sp
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -351,7 +351,7 @@ def test_invalid_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -364,7 +364,7 @@ def test_invalid_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD,
|
||||
|
@ -382,7 +382,7 @@ def test_invalid_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec,
|
|||
# Failure cases in which the withdrawals in the execution_payload are incorrect
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_withdrawal_index(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
|
||||
|
@ -395,7 +395,7 @@ def test_invalid_incorrect_withdrawal_index(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_address_full(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
|
||||
|
@ -408,7 +408,7 @@ def test_invalid_incorrect_address_full(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_address_partial(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=1)
|
||||
|
@ -421,7 +421,7 @@ def test_invalid_incorrect_address_partial(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_amount_full(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
|
||||
|
@ -434,7 +434,7 @@ def test_invalid_incorrect_amount_full(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_incorrect_amount_partial(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=1)
|
||||
|
@ -447,7 +447,7 @@ def test_invalid_incorrect_amount_partial(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_one_of_many_incorrectly_full(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -466,7 +466,7 @@ def test_invalid_one_of_many_incorrectly_full(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_one_of_many_incorrectly_partial(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -485,7 +485,7 @@ def test_invalid_one_of_many_incorrectly_partial(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_many_incorrectly_full(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_full_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -504,7 +504,7 @@ def test_invalid_many_incorrectly_full(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_many_incorrectly_partial(spec, state):
|
||||
prepare_expected_withdrawals(spec, state, num_partial_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD * 4)
|
||||
|
@ -527,7 +527,7 @@ def test_invalid_many_incorrectly_partial(spec, state):
|
|||
# More full withdrawal cases
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_withdrawable_epoch_but_0_balance(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -541,7 +541,7 @@ def test_withdrawable_epoch_but_0_balance(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -555,7 +555,7 @@ def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -569,7 +569,7 @@ def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state)
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_no_withdrawals_but_some_next_epoch(spec, state):
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
@ -583,7 +583,7 @@ def test_no_withdrawals_but_some_next_epoch(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_all_withdrawal(spec, state):
|
||||
# Make all validators withdrawable
|
||||
|
@ -619,25 +619,25 @@ def run_random_full_withdrawals_test(spec, state, rng):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_full_withdrawals_0(spec, state):
|
||||
yield from run_random_full_withdrawals_test(spec, state, random.Random(444))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_full_withdrawals_1(spec, state):
|
||||
yield from run_random_full_withdrawals_test(spec, state, random.Random(420))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_full_withdrawals_2(spec, state):
|
||||
yield from run_random_full_withdrawals_test(spec, state, random.Random(200))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_full_withdrawals_3(spec, state):
|
||||
yield from run_random_full_withdrawals_test(spec, state, random.Random(2000000))
|
||||
|
@ -647,7 +647,7 @@ def test_random_full_withdrawals_3(spec, state):
|
|||
# More partial withdrawal cases
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_no_max_effective_balance(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
@ -663,7 +663,7 @@ def test_success_no_max_effective_balance(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_no_excess_balance(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
@ -679,7 +679,7 @@ def test_success_no_excess_balance(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_excess_balance_but_no_max_effective_balance(spec, state):
|
||||
validator_index = len(state.validators) // 2
|
||||
|
@ -696,7 +696,7 @@ def test_success_excess_balance_but_no_max_effective_balance(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawable_not_yet_active(spec, state):
|
||||
validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1)
|
||||
|
@ -710,7 +710,7 @@ def test_success_one_partial_withdrawable_not_yet_active(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawable_in_exit_queue(spec, state):
|
||||
validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1)
|
||||
|
@ -725,7 +725,7 @@ def test_success_one_partial_withdrawable_in_exit_queue(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawable_exited(spec, state):
|
||||
validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1)
|
||||
|
@ -739,7 +739,7 @@ def test_success_one_partial_withdrawable_exited(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawable_active_and_slashed(spec, state):
|
||||
validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1)
|
||||
|
@ -753,7 +753,7 @@ def test_success_one_partial_withdrawable_active_and_slashed(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_one_partial_withdrawable_exited_and_slashed(spec, state):
|
||||
validator_index = min(len(state.validators) // 2, spec.MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP - 1)
|
||||
|
@ -768,7 +768,7 @@ def test_success_one_partial_withdrawable_exited_and_slashed(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_two_partial_withdrawable(spec, state):
|
||||
set_validator_partially_withdrawable(spec, state, 0)
|
||||
|
@ -779,7 +779,7 @@ def test_success_two_partial_withdrawable(spec, state):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=2)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_max_partial_withdrawable(spec, state):
|
||||
# Sanity check that this test works for this state
|
||||
|
@ -794,7 +794,7 @@ def test_success_max_partial_withdrawable(spec, state):
|
|||
spec, state, execution_payload, num_expected_withdrawals=spec.MAX_WITHDRAWALS_PER_PAYLOAD)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@with_presets([MINIMAL], reason="not enough validators with mainnet config")
|
||||
@spec_state_test
|
||||
def test_success_max_plus_one_withdrawable(spec, state):
|
||||
|
@ -833,37 +833,37 @@ def run_random_partial_withdrawals_test(spec, state, rng):
|
|||
yield from run_withdrawals_processing(spec, state, execution_payload)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_0(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(0))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_partial_withdrawals_1(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(1))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_partial_withdrawals_2(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(2))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_partial_withdrawals_3(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(3))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_partial_withdrawals_4(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(4))
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_random_partial_withdrawals_5(spec, state):
|
||||
yield from run_random_partial_withdrawals_test(spec, state, random.Random(5))
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_capella_and_later,
|
||||
)
|
||||
from eth2spec.test.helpers.epoch_processing import (
|
||||
run_epoch_processing_with
|
||||
)
|
||||
|
||||
|
||||
def run_process_historical_summaries_update(spec, state):
|
||||
yield from run_epoch_processing_with(spec, state, 'process_historical_summaries_update')
|
||||
|
||||
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_historical_summaries_accumulator(spec, state):
|
||||
# skip ahead to near the end of the historical batch period (excl block before epoch processing)
|
||||
state.slot = spec.SLOTS_PER_HISTORICAL_ROOT - 1
|
||||
pre_historical_summaries = state.historical_summaries.copy()
|
||||
|
||||
yield from run_process_historical_summaries_update(spec, state)
|
||||
|
||||
assert len(state.historical_summaries) == len(pre_historical_summaries) + 1
|
||||
summary = state.historical_summaries[len(state.historical_summaries) - 1]
|
||||
assert summary.block_summary_root == state.block_roots.hash_tree_root()
|
||||
assert summary.state_summary_root == state.state_roots.hash_tree_root()
|
|
@ -1,7 +1,6 @@
|
|||
from eth2spec.test.context import (
|
||||
with_phases, spec_state_test
|
||||
with_capella_and_later, spec_state_test
|
||||
)
|
||||
from eth2spec.test.helpers.constants import CAPELLA
|
||||
from eth2spec.test.helpers.state import (
|
||||
state_transition_and_sign_block,
|
||||
)
|
||||
|
@ -25,7 +24,7 @@ from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits
|
|||
# BLSToExecutionChange
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_bls_change(spec, state):
|
||||
index = 0
|
||||
|
@ -48,7 +47,7 @@ def test_success_bls_change(spec, state):
|
|||
assert post_credentials[12:] == signed_address_change.message.to_execution_address
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_success_exit_and_bls_change(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
|
@ -77,7 +76,7 @@ def test_success_exit_and_bls_change(spec, state):
|
|||
assert spec.is_fully_withdrawable_validator(validator, balance, validator.withdrawable_epoch)
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_duplicate_bls_changes_same_block(spec, state):
|
||||
index = 0
|
||||
|
@ -96,7 +95,7 @@ def test_invalid_duplicate_bls_changes_same_block(spec, state):
|
|||
yield 'post', None
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_two_bls_changes_of_different_addresses_same_validator_same_block(spec, state):
|
||||
index = 0
|
||||
|
@ -124,7 +123,7 @@ def test_invalid_two_bls_changes_of_different_addresses_same_validator_same_bloc
|
|||
# Withdrawals
|
||||
#
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_full_withdrawal_in_epoch_transition(spec, state):
|
||||
index = 0
|
||||
|
@ -145,7 +144,7 @@ def test_full_withdrawal_in_epoch_transition(spec, state):
|
|||
assert len(spec.get_expected_withdrawals(state)) == 0
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_partial_withdrawal_in_epoch_transition(spec, state):
|
||||
index = state.next_withdrawal_index
|
||||
|
@ -169,7 +168,7 @@ def test_partial_withdrawal_in_epoch_transition(spec, state):
|
|||
assert len(spec.get_expected_withdrawals(state)) == 0
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_many_partial_withdrawals_in_epoch_transition(spec, state):
|
||||
assert len(state.validators) > spec.MAX_WITHDRAWALS_PER_PAYLOAD
|
||||
|
@ -221,7 +220,7 @@ def _perform_valid_withdrawal(spec, state):
|
|||
return pre_state, signed_block_1, pre_next_withdrawal_index
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_withdrawal_success_two_blocks(spec, state):
|
||||
pre_state, signed_block_1, pre_next_withdrawal_index = _perform_valid_withdrawal(spec, state)
|
||||
|
@ -238,7 +237,7 @@ def test_withdrawal_success_two_blocks(spec, state):
|
|||
yield 'post', state
|
||||
|
||||
|
||||
@with_phases([CAPELLA])
|
||||
@with_capella_and_later
|
||||
@spec_state_test
|
||||
def test_invalid_withdrawal_fail_second_block_payload_isnt_compatible(spec, state):
|
||||
_perform_valid_withdrawal(spec, state)
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_eip4844_and_later
|
||||
|
||||
|
||||
def run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change, valid=True):
|
||||
"""
|
||||
Run ``process_bls_to_execution_change``, yielding:
|
||||
- pre-state ('pre')
|
||||
- address-change ('address_change')
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
pre_state = state.copy()
|
||||
|
||||
# yield pre-state
|
||||
yield 'pre', state
|
||||
|
||||
yield 'address_change', signed_address_change
|
||||
|
||||
# If the address_change is invalid, processing is aborted, and there is no post-state.
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_bls_to_execution_change(state, signed_address_change))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
# process address change
|
||||
spec.process_bls_to_execution_change(state, signed_address_change)
|
||||
|
||||
# yield post-state
|
||||
yield 'post', state
|
||||
|
||||
# Make sure state has NOT been changed
|
||||
assert state == pre_state
|
||||
|
||||
|
||||
@with_eip4844_and_later
|
||||
@spec_state_test
|
||||
def test_no_op(spec, state):
|
||||
signed_address_change = get_signed_address_change(spec, state)
|
||||
yield from run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change)
|
|
@ -1,41 +0,0 @@
|
|||
|
||||
from eth2spec.test.context import spec_state_test, expect_assertion_error, with_eip4844_and_later
|
||||
from eth2spec.test.helpers.execution_payload import (
|
||||
build_empty_execution_payload,
|
||||
)
|
||||
from eth2spec.test.helpers.state import next_slot
|
||||
|
||||
|
||||
def run_withdrawals_processing(spec, state, execution_payload, valid=True):
|
||||
"""
|
||||
Run ``process_execution_payload``, yielding:
|
||||
- pre-state ('pre')
|
||||
- execution payload ('execution_payload')
|
||||
- post-state ('post').
|
||||
If ``valid == False``, run expecting ``AssertionError``
|
||||
"""
|
||||
pre_state = state.copy()
|
||||
|
||||
yield 'pre', state
|
||||
yield 'execution_payload', execution_payload
|
||||
|
||||
if not valid:
|
||||
expect_assertion_error(lambda: spec.process_withdrawals(state, execution_payload))
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
spec.process_withdrawals(state, execution_payload)
|
||||
|
||||
yield 'post', state
|
||||
|
||||
# Make sure state has NOT been changed
|
||||
assert state == pre_state
|
||||
|
||||
|
||||
@with_eip4844_and_later
|
||||
@spec_state_test
|
||||
def test_no_op(spec, state):
|
||||
next_slot(spec, state)
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
yield from run_withdrawals_processing(spec, state, execution_payload)
|
|
@ -1,5 +1,8 @@
|
|||
|
||||
from eth2spec.test.helpers.forks import is_post_altair
|
||||
from eth2spec.test.helpers.forks import (
|
||||
is_post_altair,
|
||||
is_post_capella,
|
||||
)
|
||||
|
||||
|
||||
def get_process_calls(spec):
|
||||
|
@ -22,7 +25,10 @@ def get_process_calls(spec):
|
|||
'process_effective_balance_updates',
|
||||
'process_slashings_reset',
|
||||
'process_randao_mixes_reset',
|
||||
'process_historical_roots_update',
|
||||
# Capella replaced `process_historical_roots_update` with `process_historical_summaries_update`
|
||||
'process_historical_summaries_update' if is_post_capella(spec) else (
|
||||
'process_historical_roots_update'
|
||||
),
|
||||
# Altair replaced `process_participation_record_updates` with `process_participation_flag_updates`
|
||||
'process_participation_flag_updates' if is_post_altair(spec) else (
|
||||
'process_participation_record_updates'
|
||||
|
|
|
@ -5,28 +5,7 @@ from eth2spec.test.helpers.sync_committee import (
|
|||
compute_aggregate_sync_committee_signature,
|
||||
compute_committee_indices,
|
||||
)
|
||||
|
||||
|
||||
def signed_block_to_header(spec, block):
|
||||
return spec.BeaconBlockHeader(
|
||||
slot=block.message.slot,
|
||||
proposer_index=block.message.proposer_index,
|
||||
parent_root=block.message.parent_root,
|
||||
state_root=block.message.state_root,
|
||||
body_root=block.message.body.hash_tree_root(),
|
||||
)
|
||||
|
||||
|
||||
def initialize_light_client_store(spec, state):
|
||||
return spec.LightClientStore(
|
||||
finalized_header=spec.BeaconBlockHeader(),
|
||||
current_sync_committee=state.current_sync_committee,
|
||||
next_sync_committee=state.next_sync_committee,
|
||||
best_valid_update=None,
|
||||
optimistic_header=spec.BeaconBlockHeader(),
|
||||
previous_max_active_participants=0,
|
||||
current_max_active_participants=0,
|
||||
)
|
||||
from math import floor
|
||||
|
||||
|
||||
def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None):
|
||||
|
@ -60,3 +39,32 @@ def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None):
|
|||
sync_committee_signature=sync_committee_signature,
|
||||
)
|
||||
return sync_aggregate, signature_slot
|
||||
|
||||
|
||||
def create_update(spec,
|
||||
attested_state,
|
||||
attested_block,
|
||||
finalized_block,
|
||||
with_next,
|
||||
with_finality,
|
||||
participation_rate):
|
||||
num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate)
|
||||
|
||||
update = spec.LightClientUpdate()
|
||||
|
||||
update.attested_header = spec.block_to_light_client_header(attested_block)
|
||||
|
||||
if with_next:
|
||||
update.next_sync_committee = attested_state.next_sync_committee
|
||||
update.next_sync_committee_branch = spec.compute_merkle_proof_for_state(
|
||||
attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
||||
|
||||
if with_finality:
|
||||
update.finalized_header = spec.block_to_light_client_header(finalized_block)
|
||||
update.finality_branch = spec.compute_merkle_proof_for_state(
|
||||
attested_state, spec.FINALIZED_ROOT_INDEX)
|
||||
|
||||
update.sync_aggregate, update.signature_slot = get_sync_aggregate(
|
||||
spec, attested_state, num_participants)
|
||||
|
||||
return update
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.context import (
|
||||
PHASE0, ALTAIR, BELLATRIX,
|
||||
spec_state_test,
|
||||
with_phases,
|
||||
)
|
||||
from eth2spec.test.helpers.epoch_processing import (
|
||||
run_epoch_processing_with
|
||||
)
|
||||
|
@ -8,7 +12,7 @@ def run_process_historical_roots_update(spec, state):
|
|||
yield from run_epoch_processing_with(spec, state, 'process_historical_roots_update')
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_phases([PHASE0, ALTAIR, BELLATRIX])
|
||||
@spec_state_test
|
||||
def test_historical_root_accumulator(spec, state):
|
||||
# skip ahead to near the end of the historical roots period (excl block before epoch processing)
|
||||
|
|
|
@ -30,7 +30,7 @@ from eth2spec.test.helpers.sync_committee import (
|
|||
compute_sync_committee_participant_reward_and_penalty,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import PHASE0, MINIMAL
|
||||
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_capella
|
||||
from eth2spec.test.context import (
|
||||
spec_test, spec_state_test, dump_skipping_message,
|
||||
with_phases, with_all_phases, single_phase,
|
||||
|
@ -1026,7 +1026,10 @@ def test_balance_driven_status_transitions(spec, state):
|
|||
@always_bls
|
||||
def test_historical_batch(spec, state):
|
||||
state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1
|
||||
pre_historical_roots_len = len(state.historical_roots)
|
||||
pre_historical_roots = state.historical_roots.copy()
|
||||
|
||||
if is_post_capella(spec):
|
||||
pre_historical_summaries = state.historical_summaries.copy()
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
|
@ -1038,7 +1041,14 @@ def test_historical_batch(spec, state):
|
|||
|
||||
assert state.slot == block.slot
|
||||
assert spec.get_current_epoch(state) % (spec.SLOTS_PER_HISTORICAL_ROOT // spec.SLOTS_PER_EPOCH) == 0
|
||||
assert len(state.historical_roots) == pre_historical_roots_len + 1
|
||||
|
||||
# check history update
|
||||
if is_post_capella(spec):
|
||||
# Frozen `historical_roots`
|
||||
assert state.historical_roots == pre_historical_roots
|
||||
assert len(state.historical_summaries) == len(pre_historical_summaries) + 1
|
||||
else:
|
||||
assert len(state.historical_roots) == len(pre_historical_roots) + 1
|
||||
|
||||
|
||||
@with_all_phases
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
from eth2spec.test.helpers.forks import (
|
||||
is_post_capella,
|
||||
)
|
||||
from eth2spec.test.helpers.state import get_state_root
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
|
@ -61,3 +64,26 @@ def test_over_epoch_boundary(spec, state):
|
|||
yield 'slots', int(slots)
|
||||
spec.process_slots(state, state.slot + slots)
|
||||
yield 'post', state
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_historical_accumulator(spec, state):
|
||||
pre_historical_roots = state.historical_roots.copy()
|
||||
|
||||
if is_post_capella(spec):
|
||||
pre_historical_summaries = state.historical_summaries.copy()
|
||||
|
||||
yield 'pre', state
|
||||
slots = spec.SLOTS_PER_HISTORICAL_ROOT
|
||||
yield 'slots', int(slots)
|
||||
spec.process_slots(state, state.slot + slots)
|
||||
yield 'post', state
|
||||
|
||||
# check history update
|
||||
if is_post_capella(spec):
|
||||
# Frozen `historical_roots`
|
||||
assert state.historical_roots == pre_historical_roots
|
||||
assert len(state.historical_summaries) == len(pre_historical_summaries) + 1
|
||||
else:
|
||||
assert len(state.historical_roots) == len(pre_historical_roots) + 1
|
||||
|
|
|
@ -41,11 +41,10 @@ Sub-transitions:
|
|||
- `effective_balance_updates`
|
||||
- `slashings_reset`
|
||||
- `randao_mixes_reset`
|
||||
- `historical_roots_update`
|
||||
- `historical_roots_update` (Phase0, Altair, Bellatrix only)
|
||||
- `historical_summaries_update` (Capella)
|
||||
- `participation_record_updates` (Phase 0 only)
|
||||
- `participation_flag_updates` (Altair)
|
||||
- `sync_committee_updates` (Altair)
|
||||
- `full_withdrawals` (Capella)
|
||||
- `partial_withdrawals` (Capella)
|
||||
|
||||
The resulting state should match the expected `post` state.
|
||||
|
|
|
@ -34,7 +34,7 @@ This excludes the other parts of the block-transition.
|
|||
Operations:
|
||||
|
||||
| *`operation-name`* | *`operation-object`* | *`input name`* | *`processing call`* |
|
||||
|-------------------------|-----------------------|----------------------|----------------------------------------------------------------------|
|
||||
|---------------------------|------------------------------|---------------------|----------------------------------------------------------------------------------|
|
||||
| `attestation` | `Attestation` | `attestation` | `process_attestation(state, attestation)` |
|
||||
| `attester_slashing` | `AttesterSlashing` | `attester_slashing` | `process_attester_slashing(state, attester_slashing)` |
|
||||
| `block_header` | `BeaconBlock` | **`block`** | `process_block_header(state, block)` |
|
||||
|
@ -43,7 +43,8 @@ Operations:
|
|||
| `voluntary_exit` | `SignedVoluntaryExit` | `voluntary_exit` | `process_voluntary_exit(state, voluntary_exit)` |
|
||||
| `sync_aggregate` | `SyncAggregate` | `sync_aggregate` | `process_sync_aggregate(state, sync_aggregate)` (new in Altair) |
|
||||
| `execution_payload` | `ExecutionPayload` | `execution_payload` | `process_execution_payload(state, execution_payload)` (new in Bellatrix) |
|
||||
| `bls_to_execution_change` | `SignedBLSToExecutionChange` | `signed_address_change` | `process_bls_to_execution_change(state, signed_address_change)` (new in Capella) |
|
||||
| `withdrawals` | `ExecutionPayload` | `execution_payload` | `process_withdrawals(state, execution_payload)` (new in Capella) |
|
||||
| `bls_to_execution_change` | `SignedBLSToExecutionChange` | `address_change` | `process_bls_to_execution_change(state, address_change)` (new in Capella) |
|
||||
|
||||
Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here.
|
||||
|
||||
|
|
|
@ -27,12 +27,11 @@ if __name__ == "__main__":
|
|||
# so no additional tests required.
|
||||
bellatrix_mods = altair_mods
|
||||
|
||||
# No epoch-processing changes in Capella and previous testing repeats with new types,
|
||||
# so no additional tests required.
|
||||
capella_mods = bellatrix_mods
|
||||
_new_capella_mods = {key: 'eth2spec.test.capella.epoch_processing.test_process_' + key for key in [
|
||||
'historical_summaries_update',
|
||||
]}
|
||||
capella_mods = combine_mods(_new_capella_mods, bellatrix_mods)
|
||||
|
||||
# No epoch-processing changes in EIP4844 and previous testing repeats with new types,
|
||||
# so no additional tests required.
|
||||
eip4844_mods = capella_mods
|
||||
|
||||
# TODO Custody Game testgen is disabled for now
|
||||
|
|
|
@ -36,11 +36,7 @@ if __name__ == "__main__":
|
|||
]}
|
||||
capella_mods = combine_mods(_new_capella_mods, bellatrix_mods)
|
||||
|
||||
_new_eip4844_mods = {key: 'eth2spec.test.eip4844.block_processing.test_process_' + key for key in [
|
||||
'bls_to_execution_change',
|
||||
'withdrawals',
|
||||
]}
|
||||
eip4844_mods = combine_mods(_new_eip4844_mods, capella_mods)
|
||||
eip4844_mods = capella_mods
|
||||
|
||||
# TODO Custody Game testgen is disabled for now
|
||||
# _new_custody_game_mods = {key: 'eth2spec.test.custody_game.block_processing.test_process_' + key for key in [
|
||||
|
|
Loading…
Reference in New Issue