mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-01 19:45:03 -05:00
Merge pull request #2390 from ethereum/config-rework
Separation of Constant, Preset and Configuration variables
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -29,3 +29,6 @@ tests/core/pyspec/test-reports
|
||||
tests/core/pyspec/eth2spec/test_results.xml
|
||||
|
||||
*.egg-info
|
||||
|
||||
# TOC tool outputs temporary files
|
||||
*.tmp
|
||||
|
||||
6
Makefile
6
Makefile
@@ -96,11 +96,11 @@ install_test:
|
||||
|
||||
test: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.altair.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
python3 -m pytest -n 4 --disable-bls --cov=eth2spec.phase0.mainnet --cov=eth2spec.altair.mainnet --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
|
||||
find_test: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
python3 -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.spec --cov=eth2spec.altair.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
python3 -m pytest -k=$(K) --disable-bls --cov=eth2spec.phase0.mainnet --cov=eth2spec.altair.mainnet --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||
|
||||
citest: pyspec
|
||||
mkdir -p tests/core/pyspec/test-reports/eth2spec; . venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
@@ -167,7 +167,7 @@ define run_generator
|
||||
if ! test -d venv; then python3 -m venv venv; fi; \
|
||||
. venv/bin/activate; \
|
||||
pip3 install -r requirements.txt; \
|
||||
python3 main.py -o $(CURRENT_DIR)/$(TEST_VECTOR_DIR) -c $(CURRENT_DIR)/$(CONFIGS_DIR); \
|
||||
python3 main.py -o $(CURRENT_DIR)/$(TEST_VECTOR_DIR); \
|
||||
echo "generator $(1) finished"
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
# Configs
|
||||
# Configurations
|
||||
|
||||
This directory contains a set of constants presets used for testing, testnets, and mainnet.
|
||||
This directory contains a set of configurations used for testing, testnets, and mainnet.
|
||||
A client binary may be compiled for a specific `PRESET_BASE`,
|
||||
and then load different configurations around that preset to participate in different networks or tests.
|
||||
|
||||
A preset file contains all the constants known for its target.
|
||||
Later-fork constants can be ignored, e.g. ignore Sharding constants as a client that only supports Phase 0 currently.
|
||||
Standard configs:
|
||||
- [`mainnet.yaml`](./mainnet.yaml): Mainnet configuration
|
||||
- [`minimal.yaml`](./minimal.yaml): Minimal configuration, used in spec-testing along with the [`minimal`](../presets/minimal) preset.
|
||||
|
||||
Not all network configurations are in scope for the specification,
|
||||
see [`github.com/eth2-clients/eth2-networks`](https://github.com/eth2-clients/eth2-networks) for common networks,
|
||||
and additional testnet assets.
|
||||
|
||||
## Forking
|
||||
|
||||
Configs are not replaced, but extended with forks. This is to support syncing from one state to the other over a fork boundary, without hot-swapping a config.
|
||||
Instead, for forks that introduce changes in a constant, the constant name is prefixed with a short abbreviation of the fork.
|
||||
Variables are not replaced but extended with forks. This is to support syncing from one state to another over a fork boundary, without hot-swapping a config.
|
||||
Instead, for forks that introduce changes in a variable, the variable name is suffixed with the fork name, e.g. `INACTIVITY_PENALTY_QUOTIENT_ALTAIR`.
|
||||
|
||||
Future-fork variables can be ignored, e.g. ignore Sharding variables as a client that only supports Phase 0 currently.
|
||||
|
||||
Over time, the need to sync an older state may be deprecated.
|
||||
In this case, the prefix on the new constant may be removed, and the old constant will keep a special name before completely being removed.
|
||||
In this case, the suffix on the new variable may be removed, and the old variable will keep a special name before completely being removed.
|
||||
|
||||
A previous iteration of forking made use of "timelines", but this collides with the definitions used in the spec (constants for special forking slots, etc.), and was not integrated sufficiently in any of the spec tools or implementations.
|
||||
A previous iteration of forking made use of "timelines", but this collides with the definitions used in the spec (variables for special forking slots, etc.), and was not integrated sufficiently in any of the spec tools or implementations.
|
||||
Instead, the config essentially doubles as fork definition now, e.g. changing the value for `ALTAIR_FORK_EPOCH` changes the fork.
|
||||
|
||||
Another reason to prefer forking through constants is the ability to program a forking moment based on context, instead of being limited to a static slot number.
|
||||
|
||||
## Format
|
||||
|
||||
Each preset is a key-value mapping.
|
||||
Each preset and configuration is a key-value mapping.
|
||||
|
||||
**Key**: an `UPPER_SNAKE_CASE` (a.k.a. "macro case") formatted string, name of the constant.
|
||||
**Key**: an `UPPER_SNAKE_CASE` (a.k.a. "macro case") formatted string, name of the variable.
|
||||
|
||||
**Value** can be either:
|
||||
- an unsigned integer number, can be up to 64 bits (incl.)
|
||||
- a hexadecimal string, prefixed with `0x`
|
||||
|
||||
Presets may contain comments to describe the values.
|
||||
|
||||
See [`mainnet/phase0.yaml`](./mainnet/phase0.yaml) for a complete example.
|
||||
This format is fully YAML compatible.
|
||||
The presets and configurations may contain comments to describe the values.
|
||||
|
||||
71
configs/mainnet.yaml
Normal file
71
configs/mainnet.yaml
Normal file
@@ -0,0 +1,71 @@
|
||||
# Mainnet config
|
||||
|
||||
# Extends the mainnet preset
|
||||
PRESET_BASE: 'mainnet'
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# `2**14` (= 16,384)
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
||||
# Dec 1, 2020, 12pm UTC
|
||||
MIN_GENESIS_TIME: 1606824000
|
||||
# Mainnet initial fork version, recommend altering for testnets
|
||||
GENESIS_FORK_VERSION: 0x00000000
|
||||
# 604800 seconds (7 days)
|
||||
GENESIS_DELAY: 604800
|
||||
|
||||
|
||||
# Forking
|
||||
# ---------------------------------------------------------------
|
||||
# Some forks are disabled for now:
|
||||
# - These may be re-assigned to another fork-version later
|
||||
# - Temporarily set to max uint64 value: 2**64 - 1
|
||||
|
||||
# Altair
|
||||
ALTAIR_FORK_VERSION: 0x01000000
|
||||
ALTAIR_FORK_EPOCH: 18446744073709551615
|
||||
# Merge
|
||||
MERGE_FORK_VERSION: 0x02000000
|
||||
MERGE_FORK_EPOCH: 18446744073709551615
|
||||
# Sharding
|
||||
SHARDING_FORK_VERSION: 0x03000000
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
# TBD, 2**32 is a placeholder. Merge transition approach is in active R&D.
|
||||
TRANSITION_TOTAL_DIFFICULTY: 4294967296
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 12 seconds
|
||||
SECONDS_PER_SLOT: 12
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 14
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
SHARD_COMMITTEE_PERIOD: 256
|
||||
# 2**11 (= 2,048) Eth1 blocks ~8 hours
|
||||
ETH1_FOLLOW_DISTANCE: 2048
|
||||
|
||||
|
||||
# Validator cycle
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**16 (= 65,536)
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# Ethereum PoW Mainnet
|
||||
DEPOSIT_CHAIN_ID: 1
|
||||
DEPOSIT_NETWORK_ID: 1
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa
|
||||
@@ -1,53 +0,0 @@
|
||||
# Mainnet preset - Altair
|
||||
|
||||
# Updated penalty values
|
||||
# ---------------------------------------------------------------
|
||||
# 3 * 2**24 (= 50,331,648)
|
||||
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648
|
||||
# 2**6 (= 64)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64
|
||||
# 2
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
|
||||
|
||||
|
||||
# Sync committee
|
||||
# ---------------------------------------------------------------
|
||||
# 2**9 (= 512)
|
||||
SYNC_COMMITTEE_SIZE: 512
|
||||
# 2**9 (= 512)
|
||||
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 512
|
||||
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_SYNC_COMMITTEE: 0x07000000
|
||||
DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF: 0x08000000
|
||||
DOMAIN_CONTRIBUTION_AND_PROOF: 0x09000000
|
||||
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
# 0x01000000
|
||||
ALTAIR_FORK_VERSION: 0x01000000
|
||||
# TBD
|
||||
ALTAIR_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Sync protocol
|
||||
# ---------------------------------------------------------------
|
||||
# 1
|
||||
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
|
||||
|
||||
|
||||
# Validator
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 4
|
||||
@@ -1,7 +0,0 @@
|
||||
# Mainnet preset - The Merge
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
MERGE_FORK_VERSION: 0x02000000
|
||||
# TBD, temporarily max uint64 value: 2**64 - 1
|
||||
MERGE_FORK_EPOCH: 18446744073709551615
|
||||
71
configs/minimal.yaml
Normal file
71
configs/minimal.yaml
Normal file
@@ -0,0 +1,71 @@
|
||||
# Minimal config
|
||||
|
||||
# Extends the minimal preset
|
||||
PRESET_BASE: 'minimal'
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 64
|
||||
# Jan 3, 2020
|
||||
MIN_GENESIS_TIME: 1578009600
|
||||
# Highest byte set to 0x01 to avoid collisions with mainnet versioning
|
||||
GENESIS_FORK_VERSION: 0x00000001
|
||||
# [customized] Faster to spin up testnets, but does not give validator reasonable warning time for genesis
|
||||
GENESIS_DELAY: 300
|
||||
|
||||
|
||||
# Forking
|
||||
# ---------------------------------------------------------------
|
||||
# Values provided for illustrative purposes.
|
||||
# Individual tests/testnets may set different values.
|
||||
|
||||
# Altair
|
||||
ALTAIR_FORK_VERSION: 0x01000001
|
||||
ALTAIR_FORK_EPOCH: 18446744073709551615
|
||||
# Merge
|
||||
MERGE_FORK_VERSION: 0x02000001
|
||||
MERGE_FORK_EPOCH: 18446744073709551615
|
||||
# Sharding
|
||||
SHARDING_FORK_VERSION: 0x03000001
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
# TBD, 2**32 is a placeholder. Merge transition approach is in active R&D.
|
||||
TRANSITION_TOTAL_DIFFICULTY: 4294967296
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] Faster for testing purposes
|
||||
SECONDS_PER_SLOT: 6
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 14
|
||||
# 2**8 (= 256) epochs
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# [customized] higher frequency of committee turnover and faster time to acceptable voluntary exit
|
||||
SHARD_COMMITTEE_PERIOD: 64
|
||||
# [customized] process deposits more quickly, but insecure
|
||||
ETH1_FOLLOW_DISTANCE: 16
|
||||
|
||||
|
||||
# Validator cycle
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**16 (= 65,536)
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# Ethereum Goerli testnet
|
||||
DEPOSIT_CHAIN_ID: 5
|
||||
DEPOSIT_NETWORK_ID: 5
|
||||
# Configured on a per testnet basis
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
||||
@@ -1,54 +0,0 @@
|
||||
# Minimal preset - Altair
|
||||
|
||||
# Updated penalty values
|
||||
# ---------------------------------------------------------------
|
||||
# 3 * 2**24 (= 50,331,648)
|
||||
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648
|
||||
# 2**6 (= 64)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64
|
||||
# 2
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
|
||||
|
||||
|
||||
# Sync committee
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
SYNC_COMMITTEE_SIZE: 32
|
||||
# [customized]
|
||||
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 8
|
||||
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_SYNC_COMMITTEE: 0x07000000
|
||||
DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF: 0x08000000
|
||||
DOMAIN_CONTRIBUTION_AND_PROOF: 0x09000000
|
||||
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] Highest byte set to 0x01 to avoid collisions with mainnet versioning
|
||||
ALTAIR_FORK_VERSION: 0x01000001
|
||||
# [customized]
|
||||
ALTAIR_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Sync protocol
|
||||
# ---------------------------------------------------------------
|
||||
# 1
|
||||
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
|
||||
|
||||
|
||||
|
||||
# Validator
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 4
|
||||
@@ -1,7 +0,0 @@
|
||||
# Minimal preset - The Merge
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
MERGE_FORK_VERSION: 0x02000001
|
||||
# TBD, temporarily max uint64 value: 2**64 - 1
|
||||
MERGE_FORK_EPOCH: 18446744073709551615
|
||||
26
presets/README.md
Normal file
26
presets/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Presets
|
||||
|
||||
Presets are more extensive than runtime configurations, and generally only applicable during compile-time.
|
||||
Each preset is defined as a directory, with YAML files per fork.
|
||||
|
||||
Configurations can extend a preset by setting the `PRESET_BASE` variable.
|
||||
An implementation may choose to only support 1 preset per build-target and should validate
|
||||
the `PRESET_BASE` variable in the config matches the running build.
|
||||
|
||||
Standard presets:
|
||||
- [`mainnet/`](./mainnet): Used in mainnet, mainnet-like testnets (e.g. Prater), and spec-testing
|
||||
- [`minimal/`](./minimal): Used in low-resource local dev testnets, and spec-testing
|
||||
|
||||
Client implementers may opt to support additional presets, e.g. for extra large beacon states for benchmarking.
|
||||
See [`/configs/`](../configs) for run-time configuration, e.g. to configure a new testnet.
|
||||
|
||||
## Forking
|
||||
|
||||
Like the [config forking](../configs/README.md#forking),
|
||||
the preset extends with every fork, instead of overwriting previous values.
|
||||
An implementation can ignore preset files as a whole for future forks,
|
||||
and can thus implement stricter compile-time warnings on unrecognized or missing variables in current forks.
|
||||
|
||||
## Format
|
||||
|
||||
The preset format matches the [config format](../configs/README.md#format).
|
||||
24
presets/mainnet/altair.yaml
Normal file
24
presets/mainnet/altair.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
# Mainnet preset - Altair
|
||||
|
||||
# Updated penalty values
|
||||
# ---------------------------------------------------------------
|
||||
# 3 * 2**24 (= 50,331,648)
|
||||
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648
|
||||
# 2**6 (= 64)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64
|
||||
# 2
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
|
||||
|
||||
|
||||
# Sync committee
|
||||
# ---------------------------------------------------------------
|
||||
# 2**9 (= 512)
|
||||
SYNC_COMMITTEE_SIZE: 512
|
||||
# 2**9 (= 512)
|
||||
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 512
|
||||
|
||||
|
||||
# Sync protocol
|
||||
# ---------------------------------------------------------------
|
||||
# 1
|
||||
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
|
||||
@@ -13,14 +13,6 @@ CUSTODY_PERIOD_TO_RANDAO_PADDING: 2048
|
||||
# 2**15 (= 32,768) epochs, ~146 days
|
||||
MAX_CHUNK_CHALLENGE_DELAY: 32768
|
||||
|
||||
# Misc parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 2**256 - 189
|
||||
CUSTODY_PRIME: 115792089237316195423570985008687907853269984665640564039457584007913129639747
|
||||
# 3
|
||||
CUSTODY_SECRETS: 3
|
||||
# 1/1024 chance of custody bit 1
|
||||
CUSTODY_PROBABILITY_EXPONENT: 10
|
||||
|
||||
# Max operations
|
||||
# ---------------------------------------------------------------
|
||||
@@ -35,14 +27,9 @@ MAX_CUSTODY_CHUNK_CHALLENGE_RESP: 16
|
||||
# 2**0 (= 1)
|
||||
MAX_CUSTODY_SLASHINGS: 1
|
||||
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE: 2
|
||||
# 2**8 (= 256)
|
||||
MINOR_REWARD_QUOTIENT: 256
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_CUSTODY_BIT_SLASHING: 0x83000000
|
||||
DOMAIN_LIGHT_SELECTION_PROOF: 0x84000000
|
||||
DOMAIN_LIGHT_AGGREGATE_AND_PROOF: 0x85000000
|
||||
3
presets/mainnet/merge.yaml
Normal file
3
presets/mainnet/merge.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Mainnet preset - The Merge
|
||||
|
||||
# No presets here.
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mainnet preset
|
||||
# Mainnet preset - Phase0
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
@@ -8,16 +8,8 @@ MAX_COMMITTEES_PER_SLOT: 64
|
||||
TARGET_COMMITTEE_SIZE: 128
|
||||
# 2**11 (= 2,048)
|
||||
MAX_VALIDATORS_PER_COMMITTEE: 2048
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**16 (= 65,536)
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
# See issue 563
|
||||
SHUFFLE_ROUND_COUNT: 90
|
||||
# `2**14` (= 16,384)
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
||||
# Dec 1, 2020, 12pm UTC
|
||||
MIN_GENESIS_TIME: 1606824000
|
||||
# 4
|
||||
HYSTERESIS_QUOTIENT: 4
|
||||
# 1 (minus 0.25)
|
||||
@@ -32,54 +24,18 @@ HYSTERESIS_UPWARD_MULTIPLIER: 5
|
||||
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8
|
||||
|
||||
|
||||
# Validator
|
||||
# ---------------------------------------------------------------
|
||||
# 2**11 (= 2,048)
|
||||
ETH1_FOLLOW_DISTANCE: 2048
|
||||
# 2**4 (= 16)
|
||||
TARGET_AGGREGATORS_PER_COMMITTEE: 16
|
||||
# 2**0 (= 1)
|
||||
RANDOM_SUBNETS_PER_VALIDATOR: 1
|
||||
# 2**8 (= 256)
|
||||
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 14
|
||||
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# Ethereum PoW Mainnet
|
||||
DEPOSIT_CHAIN_ID: 1
|
||||
DEPOSIT_NETWORK_ID: 1
|
||||
# **TBD**
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa
|
||||
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
MIN_DEPOSIT_AMOUNT: 1000000000
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE: 32000000000
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
EFFECTIVE_BALANCE_INCREMENT: 1000000000
|
||||
|
||||
|
||||
# Initial values
|
||||
# ---------------------------------------------------------------
|
||||
# Mainnet initial fork version, recommend altering for testnets
|
||||
GENESIS_FORK_VERSION: 0x00000000
|
||||
BLS_WITHDRAWAL_PREFIX: 0x00
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 604800 seconds (7 days)
|
||||
GENESIS_DELAY: 604800
|
||||
# 12 seconds
|
||||
SECONDS_PER_SLOT: 12
|
||||
# 2**0 (= 1) slots 12 seconds
|
||||
MIN_ATTESTATION_INCLUSION_DELAY: 1
|
||||
# 2**5 (= 32) slots 6.4 minutes
|
||||
@@ -90,17 +46,13 @@ MIN_SEED_LOOKAHEAD: 1
|
||||
MAX_SEED_LOOKAHEAD: 4
|
||||
# 2**6 (= 64) epochs ~6.8 hours
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD: 64
|
||||
# 2**13 (= 8,192) slots ~13 hours
|
||||
# 2**13 (= 8,192) slots ~27 hours
|
||||
SLOTS_PER_HISTORICAL_ROOT: 8192
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
SHARD_COMMITTEE_PERIOD: 256
|
||||
# 2**2 (= 4) epochs 25.6 minutes
|
||||
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||
|
||||
|
||||
# State vector lengths
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
# 2**16 (= 65,536) epochs ~0.8 years
|
||||
EPOCHS_PER_HISTORICAL_VECTOR: 65536
|
||||
@@ -140,14 +92,3 @@ MAX_ATTESTATIONS: 128
|
||||
MAX_DEPOSITS: 16
|
||||
# 2**4 (= 16)
|
||||
MAX_VOLUNTARY_EXITS: 16
|
||||
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_BEACON_PROPOSER: 0x00000000
|
||||
DOMAIN_BEACON_ATTESTER: 0x01000000
|
||||
DOMAIN_RANDAO: 0x02000000
|
||||
DOMAIN_DEPOSIT: 0x03000000
|
||||
DOMAIN_VOLUNTARY_EXIT: 0x04000000
|
||||
DOMAIN_SELECTION_PROOF: 0x05000000
|
||||
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
|
||||
@@ -1,12 +1,5 @@
|
||||
# Mainnet preset - Sharding
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
SHARDING_FORK_VERSION: 0x03000000
|
||||
# TBD, temporarily max uint64 value: 2**64 - 1
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Beacon-chain
|
||||
# ---------------------------------------------------------------
|
||||
# Misc
|
||||
@@ -33,8 +26,3 @@ TARGET_SAMPLES_PER_BLOCK: 1024
|
||||
MAX_GASPRICE: 8589934592
|
||||
# 2**3 (= 8) Gwei
|
||||
MIN_GASPRICE: 8
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_SHARD_PROPOSER: 0x80000000
|
||||
DOMAIN_SHARD_COMMITTEE: 0x81000000
|
||||
24
presets/minimal/altair.yaml
Normal file
24
presets/minimal/altair.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
# Minimal preset - Altair
|
||||
|
||||
# Updated penalty values
|
||||
# ---------------------------------------------------------------
|
||||
# 3 * 2**24 (= 50,331,648)
|
||||
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648
|
||||
# 2**6 (= 64)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64
|
||||
# 2
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
|
||||
|
||||
|
||||
# Sync committee
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
SYNC_COMMITTEE_SIZE: 32
|
||||
# [customized]
|
||||
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 8
|
||||
|
||||
|
||||
# Sync protocol
|
||||
# ---------------------------------------------------------------
|
||||
# 1
|
||||
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
|
||||
@@ -13,14 +13,6 @@ CUSTODY_PERIOD_TO_RANDAO_PADDING: 8
|
||||
# [customize for faster testing]
|
||||
MAX_CHUNK_CHALLENGE_DELAY: 64
|
||||
|
||||
# Misc parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 2**256 - 189
|
||||
CUSTODY_PRIME: 115792089237316195423570985008687907853269984665640564039457584007913129639747
|
||||
# 3
|
||||
CUSTODY_SECRETS: 3
|
||||
# 1/4 chance of custody bit 1 [customized for faster testing]
|
||||
CUSTODY_PROBABILITY_EXPONENT: 2
|
||||
|
||||
# Max operations
|
||||
# ---------------------------------------------------------------
|
||||
@@ -35,14 +27,9 @@ MAX_CUSTODY_CHUNK_CHALLENGE_RESP: 8
|
||||
# 2**0 (= 1)
|
||||
MAX_CUSTODY_SLASHINGS: 1
|
||||
|
||||
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE: 2
|
||||
# 2**8 (= 256)
|
||||
MINOR_REWARD_QUOTIENT: 256
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_CUSTODY_BIT_SLASHING: 0x83000000
|
||||
DOMAIN_LIGHT_SELECTION_PROOF: 0x84000000
|
||||
DOMAIN_LIGHT_AGGREGATE_AND_PROOF: 0x85000000
|
||||
3
presets/minimal/merge.yaml
Normal file
3
presets/minimal/merge.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Minimal preset - The Merge
|
||||
|
||||
# No presets here.
|
||||
@@ -1,24 +1,15 @@
|
||||
# Minimal preset
|
||||
# Minimal preset - Phase0
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
# [customized] Just 4 committees for slot for testing purposes
|
||||
MAX_COMMITTEES_PER_SLOT: 4
|
||||
# [customized] unsecure, but fast
|
||||
TARGET_COMMITTEE_SIZE: 4
|
||||
# 2**11 (= 2,048)
|
||||
MAX_VALIDATORS_PER_COMMITTEE: 2048
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**16 (= 65,536)
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
# [customized] Faster, but unsecure.
|
||||
SHUFFLE_ROUND_COUNT: 10
|
||||
# [customized]
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 64
|
||||
# Jan 3, 2020
|
||||
MIN_GENESIS_TIME: 1578009600
|
||||
# 4
|
||||
HYSTERESIS_QUOTIENT: 4
|
||||
# 1 (minus 0.25)
|
||||
@@ -33,54 +24,18 @@ HYSTERESIS_UPWARD_MULTIPLIER: 5
|
||||
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 2
|
||||
|
||||
|
||||
# Validator
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] process deposits more quickly, but insecure
|
||||
ETH1_FOLLOW_DISTANCE: 16
|
||||
# 2**4 (= 16)
|
||||
TARGET_AGGREGATORS_PER_COMMITTEE: 16
|
||||
# 2**0 (= 1)
|
||||
RANDOM_SUBNETS_PER_VALIDATOR: 1
|
||||
# 2**8 (= 256)
|
||||
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 14
|
||||
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# Ethereum Goerli testnet
|
||||
DEPOSIT_CHAIN_ID: 5
|
||||
DEPOSIT_NETWORK_ID: 5
|
||||
# Configured on a per testnet basis
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
||||
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
MIN_DEPOSIT_AMOUNT: 1000000000
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE: 32000000000
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
EFFECTIVE_BALANCE_INCREMENT: 1000000000
|
||||
|
||||
|
||||
# Initial values
|
||||
# ---------------------------------------------------------------
|
||||
# Highest byte set to 0x01 to avoid collisions with mainnet versioning
|
||||
GENESIS_FORK_VERSION: 0x00000001
|
||||
BLS_WITHDRAWAL_PREFIX: 0x00
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] Faster to spin up testnets, but does not give validator reasonable warning time for genesis
|
||||
GENESIS_DELAY: 300
|
||||
# [customized] Faster for testing purposes
|
||||
SECONDS_PER_SLOT: 6
|
||||
# 2**0 (= 1) slots 6 seconds
|
||||
MIN_ATTESTATION_INCLUSION_DELAY: 1
|
||||
# [customized] fast epochs
|
||||
@@ -93,15 +48,11 @@ MAX_SEED_LOOKAHEAD: 4
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD: 4
|
||||
# [customized] smaller state
|
||||
SLOTS_PER_HISTORICAL_ROOT: 64
|
||||
# 2**8 (= 256) epochs
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# [customized] higher frequency of committee turnover and faster time to acceptable voluntary exit
|
||||
SHARD_COMMITTEE_PERIOD: 64
|
||||
# 2**2 (= 4) epochs
|
||||
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||
|
||||
|
||||
# State vector lengths
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] smaller state
|
||||
EPOCHS_PER_HISTORICAL_VECTOR: 64
|
||||
@@ -141,14 +92,3 @@ MAX_ATTESTATIONS: 128
|
||||
MAX_DEPOSITS: 16
|
||||
# 2**4 (= 16)
|
||||
MAX_VOLUNTARY_EXITS: 16
|
||||
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_BEACON_PROPOSER: 0x00000000
|
||||
DOMAIN_BEACON_ATTESTER: 0x01000000
|
||||
DOMAIN_RANDAO: 0x02000000
|
||||
DOMAIN_DEPOSIT: 0x03000000
|
||||
DOMAIN_VOLUNTARY_EXIT: 0x04000000
|
||||
DOMAIN_SELECTION_PROOF: 0x05000000
|
||||
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
|
||||
@@ -1,12 +1,5 @@
|
||||
# Minimal preset - Sharding
|
||||
|
||||
# Fork
|
||||
# ---------------------------------------------------------------
|
||||
SHARDING_FORK_VERSION: 0x03000001
|
||||
# TBD, temporarily max uint64 value: 2**64 - 1
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Beacon-chain
|
||||
# ---------------------------------------------------------------
|
||||
# Misc
|
||||
@@ -33,8 +26,3 @@ TARGET_SAMPLES_PER_BLOCK: 1024
|
||||
MAX_GASPRICE: 8589934592
|
||||
# 2**3 (= 8) Gwei
|
||||
MIN_GASPRICE: 8
|
||||
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_SHARD_PROPOSER: 0x80000000
|
||||
DOMAIN_SHARD_COMMITTEE: 0x81000000
|
||||
314
setup.py
314
setup.py
@@ -2,16 +2,26 @@ from setuptools import setup, find_packages, Command
|
||||
from setuptools.command.build_py import build_py
|
||||
from distutils import dir_util
|
||||
from distutils.util import convert_path
|
||||
from pathlib import Path
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import textwrap
|
||||
from typing import Dict, NamedTuple, List, Sequence, Optional
|
||||
from typing import Dict, NamedTuple, List, Sequence, Optional, TypeVar
|
||||
from abc import ABC, abstractmethod
|
||||
import ast
|
||||
|
||||
|
||||
# NOTE: have to programmatically include third-party dependencies in `setup.py`.
|
||||
RUAMEL_YAML_VERSION = "ruamel.yaml==0.16.5"
|
||||
try:
|
||||
import ruamel.yaml
|
||||
except ImportError:
|
||||
import pip
|
||||
pip.main(["install", RUAMEL_YAML_VERSION])
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
MARKO_VERSION = "marko==1.0.2"
|
||||
try:
|
||||
import marko
|
||||
@@ -30,10 +40,6 @@ PHASE0 = 'phase0'
|
||||
ALTAIR = 'altair'
|
||||
MERGE = 'merge'
|
||||
|
||||
CONFIG_LOADER = '''
|
||||
apply_constants_config(globals())
|
||||
'''
|
||||
|
||||
# The helper functions that are used when defining constants
|
||||
CONSTANT_DEP_SUNDRY_CONSTANTS_FUNCTIONS = '''
|
||||
def ceillog2(x: int) -> uint64:
|
||||
@@ -54,11 +60,19 @@ class ProtocolDefinition(NamedTuple):
|
||||
functions: Dict[str, str]
|
||||
|
||||
|
||||
class VariableDefinition(NamedTuple):
|
||||
type_name: Optional[str]
|
||||
value: str
|
||||
comment: Optional[str] # e.g. "noqa: E501"
|
||||
|
||||
|
||||
class SpecObject(NamedTuple):
|
||||
functions: Dict[str, str]
|
||||
protocols: Dict[str, ProtocolDefinition]
|
||||
custom_types: Dict[str, str]
|
||||
constants: Dict[str, str]
|
||||
constant_vars: Dict[str, VariableDefinition]
|
||||
preset_vars: Dict[str, VariableDefinition]
|
||||
config_vars: Dict[str, VariableDefinition]
|
||||
ssz_dep_constants: Dict[str, str] # the constants that depend on ssz_objects
|
||||
ssz_objects: Dict[str, str]
|
||||
dataclasses: Dict[str, str]
|
||||
@@ -124,10 +138,26 @@ def _get_eth2_spec_comment(child: LinkRefDef) -> Optional[str]:
|
||||
return title[len(ETH2_SPEC_COMMENT_PREFIX):].strip()
|
||||
|
||||
|
||||
def get_spec(file_name: str) -> SpecObject:
|
||||
def _parse_value(name: str, typed_value: str) -> VariableDefinition:
|
||||
comment = None
|
||||
if name == "BLS12_381_Q":
|
||||
comment = "noqa: E501"
|
||||
|
||||
typed_value = typed_value.strip()
|
||||
if '(' not in typed_value:
|
||||
return VariableDefinition(type_name=None, value=typed_value, comment=comment)
|
||||
i = typed_value.index('(')
|
||||
type_name = typed_value[:i]
|
||||
|
||||
return VariableDefinition(type_name=type_name, value=typed_value[i+1:-1], comment=comment)
|
||||
|
||||
|
||||
def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str]) -> SpecObject:
|
||||
functions: Dict[str, str] = {}
|
||||
protocols: Dict[str, ProtocolDefinition] = {}
|
||||
constants: Dict[str, str] = {}
|
||||
constant_vars: Dict[str, VariableDefinition] = {}
|
||||
preset_vars: Dict[str, VariableDefinition] = {}
|
||||
config_vars: Dict[str, VariableDefinition] = {}
|
||||
ssz_dep_constants: Dict[str, str] = {}
|
||||
ssz_objects: Dict[str, str] = {}
|
||||
dataclasses: Dict[str, str] = {}
|
||||
@@ -178,18 +208,31 @@ def get_spec(file_name: str) -> SpecObject:
|
||||
if len(cells) >= 2:
|
||||
name_cell = cells[0]
|
||||
name = name_cell.children[0].children
|
||||
|
||||
value_cell = cells[1]
|
||||
value = value_cell.children[0].children
|
||||
if isinstance(value, list):
|
||||
# marko parses `**X**` as a list containing a X
|
||||
value = value[0].children
|
||||
if _is_constant_id(name):
|
||||
if value.startswith("get_generalized_index"):
|
||||
ssz_dep_constants[name] = value
|
||||
else:
|
||||
constants[name] = value.replace("TBD", "2**32")
|
||||
elif value.startswith("uint") or value.startswith("Bytes") or value.startswith("ByteList"):
|
||||
custom_types[name] = value
|
||||
|
||||
if not _is_constant_id(name):
|
||||
# Check for short type declarations
|
||||
if value.startswith("uint") or value.startswith("Bytes") or value.startswith("ByteList"):
|
||||
custom_types[name] = value
|
||||
continue
|
||||
|
||||
if value.startswith("get_generalized_index"):
|
||||
ssz_dep_constants[name] = value
|
||||
continue
|
||||
|
||||
value_def = _parse_value(name, value)
|
||||
if name in preset:
|
||||
preset_vars[name] = VariableDefinition(value_def.type_name, preset[name], value_def.comment)
|
||||
elif name in config:
|
||||
config_vars[name] = VariableDefinition(value_def.type_name, config[name], value_def.comment)
|
||||
else:
|
||||
constant_vars[name] = value_def
|
||||
|
||||
elif isinstance(child, LinkRefDef):
|
||||
comment = _get_eth2_spec_comment(child)
|
||||
if comment == "skip":
|
||||
@@ -199,7 +242,9 @@ def get_spec(file_name: str) -> SpecObject:
|
||||
functions=functions,
|
||||
protocols=protocols,
|
||||
custom_types=custom_types,
|
||||
constants=constants,
|
||||
constant_vars=constant_vars,
|
||||
preset_vars=preset_vars,
|
||||
config_vars=config_vars,
|
||||
ssz_dep_constants=ssz_dep_constants,
|
||||
ssz_objects=ssz_objects,
|
||||
dataclasses=dataclasses,
|
||||
@@ -214,7 +259,7 @@ class SpecBuilder(ABC):
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def imports(cls) -> str:
|
||||
def imports(cls, preset_name: str) -> str:
|
||||
"""
|
||||
Import objects from other libraries.
|
||||
"""
|
||||
@@ -246,7 +291,7 @@ class SpecBuilder(ABC):
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def hardcoded_custom_type_dep_constants(cls) -> Dict[str, str]:
|
||||
def hardcoded_custom_type_dep_constants(cls) -> Dict[str, str]: # TODO
|
||||
"""
|
||||
The constants that are required for custom types.
|
||||
"""
|
||||
@@ -262,7 +307,8 @@ class SpecBuilder(ABC):
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def build_spec(cls, source_files: List[str]) -> str:
|
||||
def build_spec(cls, preset_name: str,
|
||||
source_files: List[Path], preset_files: Sequence[Path], config_file: Path) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -273,17 +319,16 @@ class Phase0SpecBuilder(SpecBuilder):
|
||||
fork: str = PHASE0
|
||||
|
||||
@classmethod
|
||||
def imports(cls) -> str:
|
||||
def imports(cls, preset_name: str) -> str:
|
||||
return '''from lru import LRU
|
||||
from dataclasses import (
|
||||
dataclass,
|
||||
field,
|
||||
)
|
||||
from typing import (
|
||||
Any, Callable, Dict, Set, Sequence, Tuple, Optional, TypeVar
|
||||
Any, Callable, Dict, Set, Sequence, Tuple, Optional, TypeVar, NamedTuple
|
||||
)
|
||||
|
||||
from eth2spec.config.config_util import apply_constants_config
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root, copy, uint_to_bytes
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
View, boolean, Container, List, Vector, uint8, uint32, uint64,
|
||||
@@ -297,7 +342,6 @@ from eth2spec.utils.hash_function import hash
|
||||
def preparations(cls) -> str:
|
||||
return '''
|
||||
SSZObject = TypeVar('SSZObject', bound=View)
|
||||
CONFIG_NAME = 'mainnet'
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
@@ -386,8 +430,9 @@ get_attesting_indices = cache_this(
|
||||
return ''
|
||||
|
||||
@classmethod
|
||||
def build_spec(cls, source_files: Sequence[str]) -> str:
|
||||
return _build_spec(cls.fork, source_files)
|
||||
def build_spec(cls, preset_name: str,
|
||||
source_files: Sequence[Path], preset_files: Sequence[Path], config_file: Path) -> str:
|
||||
return _build_spec(preset_name, cls.fork, source_files, preset_files, config_file)
|
||||
|
||||
|
||||
#
|
||||
@@ -397,21 +442,17 @@ class AltairSpecBuilder(Phase0SpecBuilder):
|
||||
fork: str = ALTAIR
|
||||
|
||||
@classmethod
|
||||
def imports(cls) -> str:
|
||||
return super().imports() + '\n' + '''
|
||||
def imports(cls, preset_name: str) -> str:
|
||||
return super().imports(preset_name) + '\n' + f'''
|
||||
from typing import NewType, Union
|
||||
from importlib import reload
|
||||
|
||||
from eth2spec.phase0 import spec as phase0
|
||||
from eth2spec.phase0 import {preset_name} as phase0
|
||||
from eth2spec.utils.ssz.ssz_typing import Path
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def preparations(cls):
|
||||
return super().preparations() + '\n' + '''
|
||||
# Whenever this spec version is loaded, make sure we have the latest phase0
|
||||
reload(phase0)
|
||||
|
||||
SSZVariableName = str
|
||||
GeneralizedIndex = NewType('GeneralizedIndex', int)
|
||||
'''
|
||||
@@ -449,19 +490,16 @@ class MergeSpecBuilder(Phase0SpecBuilder):
|
||||
fork: str = MERGE
|
||||
|
||||
@classmethod
|
||||
def imports(cls):
|
||||
return super().imports() + '''
|
||||
def imports(cls, preset_name: str):
|
||||
return super().imports(preset_name) + f'''
|
||||
from typing import Protocol
|
||||
from eth2spec.phase0 import spec as phase0
|
||||
from eth2spec.phase0 import {preset_name} as phase0
|
||||
from eth2spec.utils.ssz.ssz_typing import Bytes20, ByteList, ByteVector, uint256
|
||||
from importlib import reload
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def preparations(cls):
|
||||
return super().preparations() + '\n' + '''
|
||||
reload(phase0)
|
||||
'''
|
||||
return super().preparations()
|
||||
|
||||
@classmethod
|
||||
def sundry_functions(cls) -> str:
|
||||
@@ -470,7 +508,8 @@ ExecutionState = Any
|
||||
|
||||
|
||||
def get_pow_block(hash: Bytes32) -> PowBlock:
|
||||
return PowBlock(block_hash=hash, is_valid=True, is_processed=True, total_difficulty=TRANSITION_TOTAL_DIFFICULTY)
|
||||
return PowBlock(block_hash=hash, is_valid=True, is_processed=True,
|
||||
total_difficulty=config.TRANSITION_TOTAL_DIFFICULTY)
|
||||
|
||||
|
||||
def get_execution_state(execution_state_root: Bytes32) -> ExecutionState:
|
||||
@@ -513,7 +552,10 @@ spec_builders = {
|
||||
}
|
||||
|
||||
|
||||
def objects_to_spec(spec_object: SpecObject, builder: SpecBuilder, ordered_class_objects: Dict[str, str]) -> str:
|
||||
def objects_to_spec(preset_name: str,
|
||||
spec_object: SpecObject,
|
||||
builder: SpecBuilder,
|
||||
ordered_class_objects: Dict[str, str]) -> str:
|
||||
"""
|
||||
Given all the objects that constitute a spec, combine them into a single pyfile.
|
||||
"""
|
||||
@@ -547,16 +589,46 @@ def objects_to_spec(spec_object: SpecObject, builder: SpecBuilder, ordered_class
|
||||
if "ceillog2" in k or "floorlog2" in k:
|
||||
del spec_object.functions[k]
|
||||
functions_spec = '\n\n\n'.join(spec_object.functions.values())
|
||||
for k in list(spec_object.constants.keys()):
|
||||
if k == "BLS12_381_Q":
|
||||
spec_object.constants[k] += " # noqa: E501"
|
||||
constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, spec_object.constants[x]), spec_object.constants))
|
||||
|
||||
# Access global dict of config vars for runtime configurables
|
||||
for name in spec_object.config_vars.keys():
|
||||
functions_spec = functions_spec.replace(name, 'config.' + name)
|
||||
|
||||
def format_config_var(name: str, vardef: VariableDefinition) -> str:
|
||||
if vardef.type_name is None:
|
||||
out = f'{name}={vardef.value}'
|
||||
else:
|
||||
out = f'{name}={vardef.type_name}({vardef.value}),'
|
||||
if vardef.comment is not None:
|
||||
out += f' # {vardef.comment}'
|
||||
return out
|
||||
|
||||
config_spec = 'class Configuration(NamedTuple):\n'
|
||||
config_spec += ' PRESET_BASE: str\n'
|
||||
config_spec += '\n'.join(f' {k}: {v.type_name if v.type_name is not None else "int"}'
|
||||
for k, v in spec_object.config_vars.items())
|
||||
config_spec += '\n\n\nconfig = Configuration(\n'
|
||||
config_spec += f' PRESET_BASE="{preset_name}",\n'
|
||||
config_spec += '\n'.join(' ' + format_config_var(k, v) for k, v in spec_object.config_vars.items())
|
||||
config_spec += '\n)\n'
|
||||
|
||||
def format_constant(name: str, vardef: VariableDefinition) -> str:
|
||||
if vardef.type_name is None:
|
||||
out = f'{name} = {vardef.value}'
|
||||
else:
|
||||
out = f'{name} = {vardef.type_name}({vardef.value})'
|
||||
if vardef.comment is not None:
|
||||
out += f' # {vardef.comment}'
|
||||
return out
|
||||
|
||||
constant_vars_spec = '# Constant vars\n' + '\n'.join(format_constant(k, v) for k, v in spec_object.constant_vars.items())
|
||||
preset_vars_spec = '# Preset vars\n' + '\n'.join(format_constant(k, v) for k, v in spec_object.preset_vars.items())
|
||||
ordered_class_objects_spec = '\n\n\n'.join(ordered_class_objects.values())
|
||||
ssz_dep_constants = '\n'.join(map(lambda x: '%s = %s' % (x, builder.hardcoded_ssz_dep_constants()[x]), builder.hardcoded_ssz_dep_constants()))
|
||||
ssz_dep_constants_verification = '\n'.join(map(lambda x: 'assert %s == %s' % (x, spec_object.ssz_dep_constants[x]), builder.hardcoded_ssz_dep_constants()))
|
||||
custom_type_dep_constants = '\n'.join(map(lambda x: '%s = %s' % (x, builder.hardcoded_custom_type_dep_constants()[x]), builder.hardcoded_custom_type_dep_constants()))
|
||||
spec = (
|
||||
builder.imports()
|
||||
builder.imports(preset_name)
|
||||
+ builder.preparations()
|
||||
+ '\n\n' + f"fork = \'{builder.fork}\'\n"
|
||||
# The constants that some SSZ containers require. Need to be defined before `new_type_definitions`
|
||||
@@ -565,8 +637,9 @@ def objects_to_spec(spec_object: SpecObject, builder: SpecBuilder, ordered_class
|
||||
+ '\n' + CONSTANT_DEP_SUNDRY_CONSTANTS_FUNCTIONS
|
||||
# The constants that some SSZ containers require. Need to be defined before `constants_spec`
|
||||
+ ('\n\n' + ssz_dep_constants if ssz_dep_constants != '' else '')
|
||||
+ '\n\n' + constants_spec
|
||||
+ '\n\n' + CONFIG_LOADER
|
||||
+ '\n\n' + constant_vars_spec
|
||||
+ '\n\n' + preset_vars_spec
|
||||
+ '\n\n\n' + config_spec
|
||||
+ '\n\n' + ordered_class_objects_spec
|
||||
+ ('\n\n\n' + protocols_spec if protocols_spec != '' else '')
|
||||
+ '\n\n\n' + functions_spec
|
||||
@@ -586,21 +659,16 @@ def combine_protocols(old_protocols: Dict[str, ProtocolDefinition],
|
||||
if key not in old_protocols:
|
||||
old_protocols[key] = value
|
||||
else:
|
||||
functions = combine_functions(old_protocols[key].functions, value.functions)
|
||||
functions = combine_dicts(old_protocols[key].functions, value.functions)
|
||||
old_protocols[key] = ProtocolDefinition(functions=functions)
|
||||
return old_protocols
|
||||
|
||||
|
||||
def combine_functions(old_functions: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]:
|
||||
for key, value in new_functions.items():
|
||||
old_functions[key] = value
|
||||
return old_functions
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]:
|
||||
for key, value in new_constants.items():
|
||||
old_constants[key] = value
|
||||
return old_constants
|
||||
def combine_dicts(old_dict: Dict[str, T], new_dict: Dict[str, T]) -> Dict[str, T]:
|
||||
return {**old_dict, **new_dict}
|
||||
|
||||
|
||||
ignored_dependencies = [
|
||||
@@ -649,28 +717,75 @@ def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:
|
||||
"""
|
||||
Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function.
|
||||
"""
|
||||
functions0, protocols0, custom_types0, constants0, ssz_dep_constants0, ssz_objects0, dataclasses0 = spec0
|
||||
functions1, protocols1, custom_types1, constants1, ssz_dep_constants1, ssz_objects1, dataclasses1 = spec1
|
||||
protocols = combine_protocols(protocols0, protocols1)
|
||||
functions = combine_functions(functions0, functions1)
|
||||
custom_types = combine_constants(custom_types0, custom_types1)
|
||||
constants = combine_constants(constants0, constants1)
|
||||
ssz_dep_constants = combine_constants(ssz_dep_constants0, ssz_dep_constants1)
|
||||
ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1, custom_types)
|
||||
dataclasses = combine_functions(dataclasses0, dataclasses1)
|
||||
protocols = combine_protocols(spec0.protocols, spec1.protocols)
|
||||
functions = combine_dicts(spec0.functions, spec1.functions)
|
||||
custom_types = combine_dicts(spec0.custom_types, spec1.custom_types)
|
||||
constant_vars = combine_dicts(spec0.constant_vars, spec1.constant_vars)
|
||||
preset_vars = combine_dicts(spec0.preset_vars, spec1.preset_vars)
|
||||
config_vars = combine_dicts(spec0.config_vars, spec1.config_vars)
|
||||
ssz_dep_constants = combine_dicts(spec0.ssz_dep_constants, spec1.ssz_dep_constants)
|
||||
ssz_objects = combine_ssz_objects(spec0.ssz_objects, spec1.ssz_objects, custom_types)
|
||||
dataclasses = combine_dicts(spec0.dataclasses, spec1.dataclasses)
|
||||
return SpecObject(
|
||||
functions=functions,
|
||||
protocols=protocols,
|
||||
custom_types=custom_types,
|
||||
constants=constants,
|
||||
constant_vars=constant_vars,
|
||||
preset_vars=preset_vars,
|
||||
config_vars=config_vars,
|
||||
ssz_dep_constants=ssz_dep_constants,
|
||||
ssz_objects=ssz_objects,
|
||||
dataclasses=dataclasses,
|
||||
)
|
||||
|
||||
|
||||
def _build_spec(fork: str, source_files: Sequence[str]) -> str:
|
||||
all_specs = [get_spec(spec) for spec in source_files]
|
||||
def parse_config_vars(conf: Dict[str, str]) -> Dict[str, str]:
|
||||
"""
|
||||
Parses a dict of basic str/int/list types into a dict for insertion into the spec code.
|
||||
"""
|
||||
out: Dict[str, str] = dict()
|
||||
for k, v in conf.items():
|
||||
if isinstance(v, str) and (v.startswith("0x") or k == 'PRESET_BASE'):
|
||||
# Represent byte data with string, to avoid misinterpretation as big-endian int.
|
||||
# Everything is either byte data or an integer, with PRESET_BASE as one exception.
|
||||
out[k] = f"'{v}'"
|
||||
else:
|
||||
out[k] = str(int(v))
|
||||
return out
|
||||
|
||||
|
||||
def load_preset(preset_files: Sequence[Path]) -> Dict[str, str]:
|
||||
"""
|
||||
Loads the a directory of preset files, merges the result into one preset.
|
||||
"""
|
||||
preset = {}
|
||||
for fork_file in preset_files:
|
||||
yaml = YAML(typ='base')
|
||||
fork_preset: dict = yaml.load(fork_file)
|
||||
if fork_preset is None: # for empty YAML files
|
||||
continue
|
||||
if not set(fork_preset.keys()).isdisjoint(preset.keys()):
|
||||
duplicates = set(fork_preset.keys()).intersection(set(preset.keys()))
|
||||
raise Exception(f"duplicate config var(s) in preset files: {', '.join(duplicates)}")
|
||||
preset.update(fork_preset)
|
||||
assert preset != {}
|
||||
return parse_config_vars(preset)
|
||||
|
||||
|
||||
def load_config(config_path: Path) -> Dict[str, str]:
|
||||
"""
|
||||
Loads the given configuration file.
|
||||
"""
|
||||
yaml = YAML(typ='base')
|
||||
config_data = yaml.load(config_path)
|
||||
return parse_config_vars(config_data)
|
||||
|
||||
|
||||
def _build_spec(preset_name: str, fork: str,
|
||||
source_files: Sequence[Path], preset_files: Sequence[Path], config_file: Path) -> str:
|
||||
preset = load_preset(preset_files)
|
||||
config = load_config(config_file)
|
||||
all_specs = [get_spec(spec, preset, config) for spec in source_files]
|
||||
|
||||
spec_object = all_specs[0]
|
||||
for value in all_specs[1:]:
|
||||
@@ -679,7 +794,13 @@ def _build_spec(fork: str, source_files: Sequence[str]) -> str:
|
||||
class_objects = {**spec_object.ssz_objects, **spec_object.dataclasses}
|
||||
dependency_order_class_objects(class_objects, spec_object.custom_types)
|
||||
|
||||
return objects_to_spec(spec_object, spec_builders[fork], class_objects)
|
||||
return objects_to_spec(preset_name, spec_object, spec_builders[fork], class_objects)
|
||||
|
||||
|
||||
class BuildTarget(NamedTuple):
|
||||
name: str
|
||||
preset_paths: List[Path]
|
||||
config_path: Path
|
||||
|
||||
|
||||
class PySpecCommand(Command):
|
||||
@@ -690,12 +811,15 @@ class PySpecCommand(Command):
|
||||
spec_fork: str
|
||||
md_doc_paths: str
|
||||
parsed_md_doc_paths: List[str]
|
||||
build_targets: str
|
||||
parsed_build_targets: List[BuildTarget]
|
||||
out_dir: str
|
||||
|
||||
# The format is (long option, short option, description).
|
||||
user_options = [
|
||||
('spec-fork=', None, "Spec fork to tag build with. Used to select md-docs defaults."),
|
||||
('md-doc-paths=', None, "List of paths of markdown files to build spec with"),
|
||||
('build-targets=', None, "Names, directory paths of compile-time presets, and default config paths."),
|
||||
('out-dir=', None, "Output directory to write spec package to")
|
||||
]
|
||||
|
||||
@@ -705,6 +829,10 @@ class PySpecCommand(Command):
|
||||
self.spec_fork = PHASE0
|
||||
self.md_doc_paths = ''
|
||||
self.out_dir = 'pyspec_output'
|
||||
self.build_targets = """
|
||||
minimal:presets/minimal:configs/minimal.yaml
|
||||
mainnet:presets/mainnet:configs/mainnet.yaml
|
||||
"""
|
||||
|
||||
def finalize_options(self):
|
||||
"""Post-process options."""
|
||||
@@ -749,16 +877,40 @@ class PySpecCommand(Command):
|
||||
if not os.path.exists(filename):
|
||||
raise Exception('Pyspec markdown input file "%s" does not exist.' % filename)
|
||||
|
||||
self.parsed_build_targets = []
|
||||
for target in self.build_targets.split():
|
||||
target = target.strip()
|
||||
data = target.split(':')
|
||||
if len(data) != 3:
|
||||
raise Exception('invalid target, expected "name:preset_dir:config_file" format, but got: %s' % target)
|
||||
name, preset_dir_path, config_path = data
|
||||
if any((c not in string.digits + string.ascii_letters) for c in name):
|
||||
raise Exception('invalid target name: "%s"' % name)
|
||||
if not os.path.exists(preset_dir_path):
|
||||
raise Exception('Preset dir "%s" does not exist' % preset_dir_path)
|
||||
_, _, preset_file_names = next(os.walk(preset_dir_path))
|
||||
preset_paths = [(Path(preset_dir_path) / name) for name in preset_file_names]
|
||||
|
||||
if not os.path.exists(config_path):
|
||||
raise Exception('Config file "%s" does not exist' % config_path)
|
||||
self.parsed_build_targets.append(BuildTarget(name, preset_paths, Path(config_path)))
|
||||
|
||||
def run(self):
|
||||
spec_str = spec_builders[self.spec_fork].build_spec(self.parsed_md_doc_paths)
|
||||
if self.dry_run:
|
||||
self.announce('dry run successfully prepared contents for spec.'
|
||||
f' out dir: "{self.out_dir}", spec fork: "{self.spec_fork}"')
|
||||
self.debug_print(spec_str)
|
||||
else:
|
||||
if not self.dry_run:
|
||||
dir_util.mkpath(self.out_dir)
|
||||
with open(os.path.join(self.out_dir, 'spec.py'), 'w') as out:
|
||||
out.write(spec_str)
|
||||
|
||||
for (name, preset_paths, config_path) in self.parsed_build_targets:
|
||||
spec_str = spec_builders[self.spec_fork].build_spec(
|
||||
name, self.parsed_md_doc_paths, preset_paths, config_path)
|
||||
if self.dry_run:
|
||||
self.announce('dry run successfully prepared contents for spec.'
|
||||
f' out dir: "{self.out_dir}", spec fork: "{self.spec_fork}", build target: "{name}"')
|
||||
self.debug_print(spec_str)
|
||||
else:
|
||||
with open(os.path.join(self.out_dir, name+'.py'), 'w') as out:
|
||||
out.write(spec_str)
|
||||
|
||||
if not self.dry_run:
|
||||
with open(os.path.join(self.out_dir, '__init__.py'), 'w') as out:
|
||||
out.write("")
|
||||
|
||||
@@ -839,11 +991,13 @@ setup(
|
||||
url="https://github.com/ethereum/eth2.0-specs",
|
||||
include_package_data=False,
|
||||
package_data={'configs': ['*.yaml'],
|
||||
'presets': ['*.yaml'],
|
||||
'specs': ['**/*.md'],
|
||||
'eth2spec': ['VERSION.txt']},
|
||||
package_dir={
|
||||
"eth2spec": "tests/core/pyspec/eth2spec",
|
||||
"configs": "configs",
|
||||
"presets": "presets",
|
||||
"specs": "specs",
|
||||
},
|
||||
packages=find_packages(where='tests/core/pyspec') + ['configs', 'specs'],
|
||||
@@ -863,8 +1017,8 @@ setup(
|
||||
"milagro_bls_binding==1.6.3",
|
||||
"dataclasses==0.6",
|
||||
"remerkleable==0.1.19",
|
||||
"ruamel.yaml==0.16.5",
|
||||
RUAMEL_YAML_VERSION,
|
||||
"lru-dict==1.1.6",
|
||||
"marko==1.0.2",
|
||||
MARKO_VERSION,
|
||||
]
|
||||
)
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
- [Constants](#constants)
|
||||
- [Participation flag indices](#participation-flag-indices)
|
||||
- [Incentivization weights](#incentivization-weights)
|
||||
- [Domain types](#domain-types)
|
||||
- [Misc](#misc)
|
||||
- [Configuration](#configuration)
|
||||
- [Preset](#preset)
|
||||
- [Updated penalty values](#updated-penalty-values)
|
||||
- [Sync committee](#sync-committee)
|
||||
- [Misc](#misc-1)
|
||||
- [Domain types](#domain-types)
|
||||
- [Configuration](#configuration)
|
||||
- [Inactivity penalties](#inactivity-penalties)
|
||||
- [Containers](#containers)
|
||||
- [Modified containers](#modified-containers)
|
||||
- [`BeaconBlockBody`](#beaconblockbody)
|
||||
@@ -27,7 +28,7 @@
|
||||
- [Helper functions](#helper-functions)
|
||||
- [`Predicates`](#predicates)
|
||||
- [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify)
|
||||
- [Misc](#misc-2)
|
||||
- [Misc](#misc-1)
|
||||
- [`add_flag`](#add_flag)
|
||||
- [`has_flag`](#has_flag)
|
||||
- [Beacon state accessors](#beacon-state-accessors)
|
||||
@@ -94,6 +95,14 @@ Altair is the first beacon chain hard fork. Its main features are:
|
||||
|
||||
*Note*: The sum of the weights equal `WEIGHT_DENOMINATOR`.
|
||||
|
||||
### Domain types
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_SYNC_COMMITTEE` | `DomainType('0x07000000')` |
|
||||
| `DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF` | `DomainType('0x08000000')` |
|
||||
| `DOMAIN_CONTRIBUTION_AND_PROOF` | `DomainType('0x09000000')` |
|
||||
|
||||
### Misc
|
||||
|
||||
| Name | Value |
|
||||
@@ -101,7 +110,7 @@ Altair is the first beacon chain hard fork. Its main features are:
|
||||
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
|
||||
| `PARTICIPATION_FLAG_WEIGHTS` | `[TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_WEIGHT, TIMELY_HEAD_WEIGHT]` |
|
||||
|
||||
## Configuration
|
||||
## Preset
|
||||
|
||||
### Updated penalty values
|
||||
|
||||
@@ -122,20 +131,14 @@ This patch updates a few configuration values to move penalty parameters closer
|
||||
| `SYNC_COMMITTEE_SIZE` | `uint64(2**9)` (= 512) | Validators | |
|
||||
| `EPOCHS_PER_SYNC_COMMITTEE_PERIOD` | `uint64(2**9)` (= 512) | epochs | ~54 hours |
|
||||
|
||||
### Misc
|
||||
## Configuration
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `INACTIVITY_SCORE_BIAS` | `uint64(4)` |
|
||||
| `INACTIVITY_SCORE_RECOVERY_RATE` | `uint64(16)` |
|
||||
### Inactivity penalties
|
||||
|
||||
### Domain types
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_SYNC_COMMITTEE` | `DomainType('0x07000000')` |
|
||||
| `DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF` | `DomainType('0x08000000')` |
|
||||
| `DOMAIN_CONTRIBUTION_AND_PROOF` | `DomainType('0x09000000')` |
|
||||
| Name | Value | Description |
|
||||
| - | - | - |
|
||||
| `INACTIVITY_SCORE_BIAS` | `uint64(4)` | score points per inactive epoch |
|
||||
| `INACTIVITY_SCORE_RECOVERY_RATE` | `uint64(16)` | score points per recovering epoch |
|
||||
|
||||
## Containers
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Constants](#constants)
|
||||
- [Configuration](#configuration)
|
||||
- [Preset](#preset)
|
||||
- [Misc](#misc)
|
||||
- [Containers](#containers)
|
||||
- [`LightClientSnapshot`](#lightclientsnapshot)
|
||||
@@ -43,7 +43,7 @@ uses sync committees introduced in [this beacon chain extension](./beacon-chain.
|
||||
| `FINALIZED_ROOT_INDEX` | `get_generalized_index(BeaconState, 'finalized_checkpoint', 'root')` |
|
||||
| `NEXT_SYNC_COMMITTEE_INDEX` | `get_generalized_index(BeaconState, 'next_sync_committee')` |
|
||||
|
||||
## Configuration
|
||||
## Preset
|
||||
|
||||
### Misc
|
||||
|
||||
|
||||
@@ -71,7 +71,13 @@ building upon the [Sharding](../sharding/beacon-chain.md) specification.
|
||||
| `BYTES_PER_CUSTODY_ATOM` | `uint64(32)` | bytes |
|
||||
| `CUSTODY_PROBABILITY_EXPONENT` | `uint64(10)` | - |
|
||||
|
||||
## Configuration
|
||||
### Domain types
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_CUSTODY_BIT_SLASHING` | `DomainType('0x83000000')` |
|
||||
|
||||
## Preset
|
||||
|
||||
### Time parameters
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
- [Constants](#constants)
|
||||
- [Execution](#execution)
|
||||
- [Configuration](#configuration)
|
||||
- [Transition](#transition)
|
||||
- [Containers](#containers)
|
||||
- [Extended containers](#extended-containers)
|
||||
- [`BeaconBlockBody`](#beaconblockbody)
|
||||
@@ -65,6 +66,8 @@ We define the following Python custom types for type hinting and readability:
|
||||
|
||||
Warning: this configuration is not definitive.
|
||||
|
||||
### Transition
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `MERGE_FORK_VERSION` | `Version('0x02000000')` |
|
||||
|
||||
@@ -9,16 +9,20 @@
|
||||
- [Notation](#notation)
|
||||
- [Custom types](#custom-types)
|
||||
- [Constants](#constants)
|
||||
- [Configuration](#configuration)
|
||||
- [Misc](#misc)
|
||||
- [Gwei values](#gwei-values)
|
||||
- [Initial values](#initial-values)
|
||||
- [Withdrawal prefixes](#withdrawal-prefixes)
|
||||
- [Domain types](#domain-types)
|
||||
- [Preset](#preset)
|
||||
- [Misc](#misc-1)
|
||||
- [Gwei values](#gwei-values)
|
||||
- [Time parameters](#time-parameters)
|
||||
- [State list lengths](#state-list-lengths)
|
||||
- [Rewards and penalties](#rewards-and-penalties)
|
||||
- [Max operations per block](#max-operations-per-block)
|
||||
- [Domain types](#domain-types)
|
||||
- [Configuration](#configuration)
|
||||
- [Genesis settings](#genesis-settings)
|
||||
- [Time parameters](#time-parameters-1)
|
||||
- [Validator cycle](#validator-cycle)
|
||||
- [Containers](#containers)
|
||||
- [Misc dependencies](#misc-dependencies)
|
||||
- [`Fork`](#fork)
|
||||
@@ -67,7 +71,7 @@
|
||||
- [`is_slashable_attestation_data`](#is_slashable_attestation_data)
|
||||
- [`is_valid_indexed_attestation`](#is_valid_indexed_attestation)
|
||||
- [`is_valid_merkle_branch`](#is_valid_merkle_branch)
|
||||
- [Misc](#misc-1)
|
||||
- [Misc](#misc-2)
|
||||
- [`compute_shuffled_index`](#compute_shuffled_index)
|
||||
- [`compute_proposer_index`](#compute_proposer_index)
|
||||
- [`compute_committee`](#compute_committee)
|
||||
@@ -170,6 +174,8 @@ We define the following Python custom types for type hinting and readability:
|
||||
|
||||
The following values are (non-configurable) constants used throughout the specification.
|
||||
|
||||
### Misc
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `GENESIS_SLOT` | `Slot(0)` |
|
||||
@@ -180,23 +186,39 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| `JUSTIFICATION_BITS_LENGTH` | `uint64(4)` |
|
||||
| `ENDIANNESS` | `'little'` |
|
||||
|
||||
## Configuration
|
||||
### Withdrawal prefixes
|
||||
|
||||
*Note*: The default mainnet configuration values are included here for illustrative purposes. The different configurations for mainnet, testnets, and YAML-based testing can be found in the [`configs/constant_presets`](../../configs) directory.
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `BLS_WITHDRAWAL_PREFIX` | `Bytes1('0x00')` |
|
||||
| `ETH1_ADDRESS_WITHDRAWAL_PREFIX` | `Bytes1('0x01')` |
|
||||
|
||||
### Domain types
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_BEACON_PROPOSER` | `DomainType('0x00000000')` |
|
||||
| `DOMAIN_BEACON_ATTESTER` | `DomainType('0x01000000')` |
|
||||
| `DOMAIN_RANDAO` | `DomainType('0x02000000')` |
|
||||
| `DOMAIN_DEPOSIT` | `DomainType('0x03000000')` |
|
||||
| `DOMAIN_VOLUNTARY_EXIT` | `DomainType('0x04000000')` |
|
||||
| `DOMAIN_SELECTION_PROOF` | `DomainType('0x05000000')` |
|
||||
| `DOMAIN_AGGREGATE_AND_PROOF` | `DomainType('0x06000000')` |
|
||||
|
||||
## Preset
|
||||
|
||||
*Note*: The below configuration is bundled as a preset: a bundle of configuration variables which are expected to differ
|
||||
between different modes of operation, e.g. testing, but not generally between different networks.
|
||||
Additional preset configurations can be found in the [`configs`](../../configs) directory.
|
||||
|
||||
### Misc
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `ETH1_FOLLOW_DISTANCE` | `uint64(2**11)` (= 2,048) |
|
||||
| `MAX_COMMITTEES_PER_SLOT` | `uint64(2**6)` (= 64) |
|
||||
| `TARGET_COMMITTEE_SIZE` | `uint64(2**7)` (= 128) |
|
||||
| `MAX_VALIDATORS_PER_COMMITTEE` | `uint64(2**11)` (= 2,048) |
|
||||
| `MIN_PER_EPOCH_CHURN_LIMIT` | `uint64(2**2)` (= 4) |
|
||||
| `CHURN_LIMIT_QUOTIENT` | `uint64(2**16)` (= 65,536) |
|
||||
| `SHUFFLE_ROUND_COUNT` | `uint64(90)` |
|
||||
| `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `uint64(2**14)` (= 16,384) |
|
||||
| `MIN_GENESIS_TIME` | `uint64(1606824000)` (Dec 1, 2020, 12pm UTC) |
|
||||
| `HYSTERESIS_QUOTIENT` | `uint64(4)` |
|
||||
| `HYSTERESIS_DOWNWARD_MULTIPLIER` | `uint64(1)` |
|
||||
| `HYSTERESIS_UPWARD_MULTIPLIER` | `uint64(5)` |
|
||||
@@ -209,29 +231,12 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| - | - |
|
||||
| `MIN_DEPOSIT_AMOUNT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) |
|
||||
| `MAX_EFFECTIVE_BALANCE` | `Gwei(2**5 * 10**9)` (= 32,000,000,000) |
|
||||
| `EJECTION_BALANCE` | `Gwei(2**4 * 10**9)` (= 16,000,000,000) |
|
||||
| `EFFECTIVE_BALANCE_INCREMENT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) |
|
||||
|
||||
### Initial values
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `GENESIS_FORK_VERSION` | `Version('0x00000000')` |
|
||||
|
||||
### Withdrawal prefixes
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `BLS_WITHDRAWAL_PREFIX` | `Bytes1('0x00')` |
|
||||
| `ETH1_ADDRESS_WITHDRAWAL_PREFIX` | `Bytes1('0x01')` |
|
||||
|
||||
### Time parameters
|
||||
|
||||
| Name | Value | Unit | Duration |
|
||||
| - | - | :-: | :-: |
|
||||
| `GENESIS_DELAY` | `uint64(604800)` | seconds | 7 days |
|
||||
| `SECONDS_PER_SLOT` | `uint64(12)` | seconds | 12 seconds |
|
||||
| `SECONDS_PER_ETH1_BLOCK` | `uint64(14)` | seconds | 14 seconds |
|
||||
| `MIN_ATTESTATION_INCLUSION_DELAY` | `uint64(2**0)` (= 1) | slots | 12 seconds |
|
||||
| `SLOTS_PER_EPOCH` | `uint64(2**5)` (= 32) | slots | 6.4 minutes |
|
||||
| `MIN_SEED_LOOKAHEAD` | `uint64(2**0)` (= 1) | epochs | 6.4 minutes |
|
||||
@@ -239,8 +244,6 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `uint64(2**2)` (= 4) | epochs | 25.6 minutes |
|
||||
| `EPOCHS_PER_ETH1_VOTING_PERIOD` | `uint64(2**6)` (= 64) | epochs | ~6.8 hours |
|
||||
| `SLOTS_PER_HISTORICAL_ROOT` | `uint64(2**13)` (= 8,192) | slots | ~27 hours |
|
||||
| `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
|
||||
| `SHARD_COMMITTEE_PERIOD` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
|
||||
|
||||
### State list lengths
|
||||
|
||||
@@ -276,17 +279,38 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| `MAX_DEPOSITS` | `2**4` (= 16) |
|
||||
| `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) |
|
||||
|
||||
### Domain types
|
||||
## Configuration
|
||||
|
||||
*Note*: The default mainnet configuration values are included here for illustrative purposes.
|
||||
Defaults for this more dynamic type of configuration are available with the presets in the [`configs`](../../configs) directory.
|
||||
Testnets and other types of chain instances may use a different configuration.
|
||||
|
||||
### Genesis settings
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_BEACON_PROPOSER` | `DomainType('0x00000000')` |
|
||||
| `DOMAIN_BEACON_ATTESTER` | `DomainType('0x01000000')` |
|
||||
| `DOMAIN_RANDAO` | `DomainType('0x02000000')` |
|
||||
| `DOMAIN_DEPOSIT` | `DomainType('0x03000000')` |
|
||||
| `DOMAIN_VOLUNTARY_EXIT` | `DomainType('0x04000000')` |
|
||||
| `DOMAIN_SELECTION_PROOF` | `DomainType('0x05000000')` |
|
||||
| `DOMAIN_AGGREGATE_AND_PROOF` | `DomainType('0x06000000')` |
|
||||
| `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT` | `uint64(2**14)` (= 16,384) |
|
||||
| `MIN_GENESIS_TIME` | `uint64(1606824000)` (Dec 1, 2020, 12pm UTC) |
|
||||
| `GENESIS_FORK_VERSION` | `Version('0x00000000')` |
|
||||
| `GENESIS_DELAY` | `uint64(604800)` (7 days) |
|
||||
|
||||
### Time parameters
|
||||
|
||||
| Name | Value | Unit | Duration |
|
||||
| - | - | :-: | :-: |
|
||||
| `SECONDS_PER_SLOT` | `uint64(12)` | seconds | 12 seconds |
|
||||
| `SECONDS_PER_ETH1_BLOCK` | `uint64(14)` | seconds | 14 seconds |
|
||||
| `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
|
||||
| `SHARD_COMMITTEE_PERIOD` | `uint64(2**8)` (= 256) | epochs | ~27 hours |
|
||||
| `ETH1_FOLLOW_DISTANCE` | `uint64(2**11)` (= 2,048) | Eth1 blocks | ~8 hours |
|
||||
|
||||
### Validator cycle
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `EJECTION_BALANCE` | `Gwei(2**4 * 10**9)` (= 16,000,000,000) |
|
||||
| `MIN_PER_EPOCH_CHURN_LIMIT` | `uint64(2**2)` (= 4) |
|
||||
| `CHURN_LIMIT_QUOTIENT` | `uint64(2**16)` (= 65,536) |
|
||||
|
||||
## Containers
|
||||
|
||||
@@ -1556,7 +1580,10 @@ def process_registry_updates(state: BeaconState) -> None:
|
||||
if is_eligible_for_activation_queue(validator):
|
||||
validator.activation_eligibility_epoch = get_current_epoch(state) + 1
|
||||
|
||||
if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE:
|
||||
if (
|
||||
is_active_validator(validator, get_current_epoch(state))
|
||||
and validator.effective_balance <= EJECTION_BALANCE
|
||||
):
|
||||
initiate_validator_exit(state, ValidatorIndex(index))
|
||||
|
||||
# Queue validators eligible for activation and not yet dequeued for activation
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Fork choice](#fork-choice)
|
||||
- [Configuration](#configuration)
|
||||
- [Preset](#preset)
|
||||
- [Helpers](#helpers)
|
||||
- [`LatestMessage`](#latestmessage)
|
||||
- [`Store`](#store)
|
||||
@@ -55,7 +55,7 @@ Any of the above handlers that trigger an unhandled exception (e.g. a failed ass
|
||||
4) **Manual forks**: Manual forks may arbitrarily change the fork choice rule but are expected to be enacted at epoch transitions, with the fork details reflected in `state.fork`.
|
||||
5) **Implementation**: The implementation found in this specification is constructed for ease of understanding rather than for optimization in computation, space, or any other resource. A number of optimized alternatives can be found [here](https://github.com/protolambda/lmd-ghost).
|
||||
|
||||
### Configuration
|
||||
### Preset
|
||||
|
||||
| Name | Value | Unit | Duration |
|
||||
| - | - | :-: | :-: |
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
- [Introduction](#introduction)
|
||||
- [Custom types](#custom-types)
|
||||
- [Constants](#constants)
|
||||
- [Configuration](#configuration)
|
||||
- [Misc](#misc)
|
||||
- [Shard block configs](#shard-block-configs)
|
||||
- [Domain types](#domain-types)
|
||||
- [Preset](#preset)
|
||||
- [Misc](#misc-1)
|
||||
- [Shard block samples](#shard-block-samples)
|
||||
- [Precomputed size verification points](#precomputed-size-verification-points)
|
||||
- [Gwei values](#gwei-values)
|
||||
- [Domain types](#domain-types)
|
||||
- [Configuration](#configuration)
|
||||
- [Updated containers](#updated-containers)
|
||||
- [`AttestationData`](#attestationdata)
|
||||
- [`BeaconBlockBody`](#beaconblockbody)
|
||||
@@ -31,7 +33,7 @@
|
||||
- [`SignedShardBlobReference`](#signedshardblobreference)
|
||||
- [`ShardProposerSlashing`](#shardproposerslashing)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc-1)
|
||||
- [Misc](#misc-2)
|
||||
- [`next_power_of_two`](#next_power_of_two)
|
||||
- [`compute_previous_slot`](#compute_previous_slot)
|
||||
- [`compute_updated_gasprice`](#compute_updated_gasprice)
|
||||
@@ -81,6 +83,8 @@ We define the following Python custom types for type hinting and readability:
|
||||
|
||||
The following values are (non-configurable) constants used throughout the specification.
|
||||
|
||||
### Misc
|
||||
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
| `PRIMITIVE_ROOT_OF_UNITY` | `5` | Primitive root of unity of the BLS12_381 (inner) modulus |
|
||||
@@ -88,19 +92,25 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| `POINTS_PER_SAMPLE` | `uint64(2**3)` (= 8) | 31 * 8 = 248 bytes |
|
||||
| `MODULUS` | `0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001` (curve order of BLS12_381) |
|
||||
|
||||
## Configuration
|
||||
### Domain types
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_SHARD_PROPOSER` | `DomainType('0x80000000')` |
|
||||
| `DOMAIN_SHARD_COMMITTEE` | `DomainType('0x81000000')` |
|
||||
|
||||
## Preset
|
||||
|
||||
### Misc
|
||||
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
| `MAX_SHARDS` | `uint64(2**10)` (= 1,024) | Theoretical max shard count (used to determine data structure sizes) |
|
||||
| `INITIAL_ACTIVE_SHARDS` | `uint64(2**6)` (= 64) | Initial shard count |
|
||||
| `GASPRICE_ADJUSTMENT_COEFFICIENT` | `uint64(2**3)` (= 8) | Gasprice may decrease/increase by at most exp(1 / this value) *per epoch* |
|
||||
| `MAX_SHARD_HEADERS_PER_SHARD` | `4` | |
|
||||
| `MAX_SHARD_PROPOSER_SLASHINGS` | `2**4` (= 16) | Maximum amount of shard proposer slashing operations per block |
|
||||
| `MAX_SHARD_HEADERS_PER_SHARD` | `4` | |
|
||||
|
||||
### Shard block configs
|
||||
### Shard block samples
|
||||
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
@@ -122,12 +132,11 @@ The following values are (non-configurable) constants used throughout the specif
|
||||
| `MAX_GASPRICE` | `Gwei(2**33)` (= 8,589,934,592) | Gwei | Max gasprice charged for a TARGET-sized shard block |
|
||||
| `MIN_GASPRICE` | `Gwei(2**3)` (= 8) | Gwei | Min gasprice charged for a TARGET-sized shard block |
|
||||
|
||||
### Domain types
|
||||
## Configuration
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `DOMAIN_SHARD_PROPOSER` | `DomainType('0x80000000')` |
|
||||
| `DOMAIN_SHARD_COMMITTEE` | `DomainType('0x81000000')` |
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
| `INITIAL_ACTIVE_SHARDS` | `uint64(2**6)` (= 64) | Initial shard count |
|
||||
|
||||
## Updated containers
|
||||
|
||||
|
||||
@@ -57,21 +57,22 @@ Caveats:
|
||||
|
||||
Full test usage, with explicit configuration for illustration of options usage:
|
||||
```shell
|
||||
(venv) python -m pytest --config=minimal eth2spec
|
||||
(venv) python -m pytest --preset=minimal eth2spec
|
||||
```
|
||||
|
||||
Or, to run a specific test file, specify the full path:
|
||||
```shell
|
||||
(venv) python -m pytest --config=minimal ./eth2spec/test/phase0/block_processing/test_process_attestation.py
|
||||
(venv) python -m pytest --preset=minimal ./eth2spec/test/phase0/block_processing/test_process_attestation.py
|
||||
```
|
||||
|
||||
Or, to run a specific test function (specify the `eth2spec` module, or the script path if the keyword is ambiguous):
|
||||
```shell
|
||||
(venv) python -m pytest --config=minimal -k test_success_multi_proposer_index_iterations eth2spec
|
||||
(venv) python -m pytest --preset=minimal -k test_success_multi_proposer_index_iterations eth2spec
|
||||
```
|
||||
|
||||
Options:
|
||||
- `--config`, to change the config. Defaults to `minimal`, can be set to `mainnet`, or other configs from the configs directory.
|
||||
- `--preset`, to change the preset (compile-time configurables). Defaults to `minimal`, can be set to `mainnet`.
|
||||
Use `@spec_configured_state_test({config here...}` to override runtime configurables on a per-test basis.
|
||||
- `--disable-bls`, to disable BLS (only for tests that can run without)
|
||||
- `--bls-type`, `milagro` or `py_ecc` (default)
|
||||
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
# Eth2 config util
|
||||
|
||||
For configuration, see [Configs documentation](../../../../../configs/README.md).
|
||||
For run-time configuration, see [Configs documentation](../../../../../configs/README.md).
|
||||
|
||||
## Usage:
|
||||
For compile-time presets, see [Presets documentation](../../../../../presets/README.md)
|
||||
and the `build-targets` flag for the `pyspec` distutils command.
|
||||
|
||||
## Config usage:
|
||||
|
||||
```python
|
||||
configs_path = 'configs/'
|
||||
|
||||
...
|
||||
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.phase0 import spec
|
||||
from importlib import reload
|
||||
config_util.prepare_config(configs_path, 'mainnet')
|
||||
# reload spec to make loaded config effective
|
||||
reload(spec)
|
||||
from eth2spec.phase0 import mainnet as spec
|
||||
from pathlib import Path
|
||||
|
||||
# To load the default configurations
|
||||
config_util.load_defaults(Path("eth2.0-specs/configs")) # change path to point to equivalent of specs `configs` dir.
|
||||
# After loading the defaults, a config can be chosen: 'mainnet', 'minimal', or custom network config (by file path)
|
||||
spec.config = spec.Configuration(**config_util.load_config_file(Path('mytestnet.yaml')))
|
||||
```
|
||||
|
||||
WARNING: this overwrites globals, make sure to prevent accidental collisions with other usage of the same imported specs package.
|
||||
Note: previously the testnet config files included both preset and runtime-configuration data.
|
||||
The new config loader is compatible with this: all config vars are loaded from the file,
|
||||
but those that have become presets can be ignored.
|
||||
|
||||
@@ -1,60 +1,63 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
|
||||
from typing import Dict, Iterable, Union, BinaryIO, TextIO, Any
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
config: Dict[str, Any] = {}
|
||||
|
||||
|
||||
# Access to overwrite spec constants based on configuration
|
||||
# This is called by the spec module after declaring its globals, and applies the loaded presets.
|
||||
def apply_constants_config(spec_globals: Dict[str, Any], warn_if_unknown: bool = False) -> None:
|
||||
global config
|
||||
for k, v in config.items():
|
||||
# the spec should have default values for everything, if not, the config key is invalid.
|
||||
if k in spec_globals:
|
||||
# Keep the same type as the default value indicates (which may be an SSZ basic type subclass, e.g. 'Gwei')
|
||||
spec_globals[k] = spec_globals[k].__class__(v)
|
||||
else:
|
||||
# Note: The phase 0 spec will not warn if Altair or later config values are applied.
|
||||
# During debugging you can enable explicit warnings.
|
||||
if warn_if_unknown:
|
||||
print(f"WARNING: unknown config key: '{k}' with value: '{v}'")
|
||||
|
||||
|
||||
# Load presets from a file, and then prepares the global config setting. This does not apply the config.
|
||||
# To apply the config, reload the spec module (it will re-initialize with the config taken from here).
|
||||
def prepare_config(configs_path: str, config_name: str) -> None:
|
||||
global config
|
||||
config = load_config_file(configs_path, config_name)
|
||||
|
||||
|
||||
def load_config_file(configs_dir: str, presets_name: str) -> Dict[str, Any]:
|
||||
def parse_config_vars(conf: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Loads the given preset
|
||||
:param presets_name: The name of the presets. (lowercase snake_case)
|
||||
:return: Dictionary, mapping of constant-name -> constant-value
|
||||
Parses a dict of basic str/int/list types into more detailed python types
|
||||
"""
|
||||
present_dir = Path(configs_dir) / presets_name
|
||||
_, _, config_files = next(os.walk(present_dir))
|
||||
config_files.sort()
|
||||
loaded_config = {}
|
||||
for config_file_name in config_files:
|
||||
yaml = YAML(typ='base')
|
||||
path = present_dir / config_file_name
|
||||
loaded = yaml.load(path)
|
||||
loaded_config.update(loaded)
|
||||
assert loaded_config != {}
|
||||
|
||||
out: Dict[str, Any] = dict()
|
||||
for k, v in loaded_config.items():
|
||||
for k, v in conf.items():
|
||||
if isinstance(v, list):
|
||||
# Clean up integer values. YAML parser renders lists of ints as list of str
|
||||
out[k] = [int(item) if item.isdigit() else item for item in v]
|
||||
elif isinstance(v, str) and v.startswith("0x"):
|
||||
out[k] = bytes.fromhex(v[2:])
|
||||
else:
|
||||
elif k != 'PRESET_BASE':
|
||||
out[k] = int(v)
|
||||
out['CONFIG_NAME'] = presets_name
|
||||
else:
|
||||
out[k] = v
|
||||
return out
|
||||
|
||||
|
||||
def load_preset(preset_files: Iterable[Union[Path, BinaryIO, TextIO]]) -> Dict[str, Any]:
|
||||
"""
|
||||
Loads the a directory of preset files, merges the result into one preset.
|
||||
"""
|
||||
preset = {}
|
||||
for fork_file in preset_files:
|
||||
yaml = YAML(typ='base')
|
||||
fork_preset: dict = yaml.load(fork_file)
|
||||
if fork_preset is None: # for empty YAML files
|
||||
continue
|
||||
if not set(fork_preset.keys()).isdisjoint(preset.keys()):
|
||||
duplicates = set(fork_preset.keys()).intersection(set(preset.keys()))
|
||||
raise Exception(f"duplicate config var(s) in preset files: {', '.join(duplicates)}")
|
||||
preset.update(fork_preset)
|
||||
assert preset != {}
|
||||
return parse_config_vars(preset)
|
||||
|
||||
|
||||
def load_config_file(config_path: Union[Path, BinaryIO, TextIO]) -> Dict[str, Any]:
|
||||
"""
|
||||
Loads the given configuration file.
|
||||
"""
|
||||
yaml = YAML(typ='base')
|
||||
config_data = yaml.load(config_path)
|
||||
return parse_config_vars(config_data)
|
||||
|
||||
|
||||
mainnet_config_data: Dict[str, Any]
|
||||
minimal_config_data: Dict[str, Any]
|
||||
loaded_defaults = False
|
||||
|
||||
|
||||
def load_defaults(spec_configs_path: Path) -> None:
|
||||
global mainnet_config_data, minimal_config_data
|
||||
|
||||
mainnet_config_data = load_config_file(spec_configs_path / 'mainnet.yaml')
|
||||
minimal_config_data = load_config_file(spec_configs_path / 'minimal.yaml')
|
||||
|
||||
global loaded_defaults
|
||||
loaded_defaults = True
|
||||
|
||||
@@ -34,18 +34,6 @@ def validate_output_dir(path_str):
|
||||
return path
|
||||
|
||||
|
||||
def validate_configs_dir(path_str):
|
||||
path = Path(path_str)
|
||||
|
||||
if not path.exists():
|
||||
raise argparse.ArgumentTypeError("Configs directory must exist")
|
||||
|
||||
if not path.is_dir():
|
||||
raise argparse.ArgumentTypeError("Config path must lead to a directory")
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def run_generator(generator_name, test_providers: Iterable[TestProvider]):
|
||||
"""
|
||||
Implementation for a general test generator.
|
||||
@@ -76,22 +64,14 @@ def run_generator(generator_name, test_providers: Iterable[TestProvider]):
|
||||
default=False,
|
||||
help="if set re-generate and overwrite test files if they already exist",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--configs-path",
|
||||
dest="configs_path",
|
||||
required=True,
|
||||
type=validate_configs_dir,
|
||||
help="specify the path of the configs directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--config-list",
|
||||
dest="config_list",
|
||||
"--preset-list",
|
||||
dest="preset_list",
|
||||
nargs='*',
|
||||
type=str,
|
||||
required=False,
|
||||
help="specify configs to run with. Allows all if no config names are specified.",
|
||||
help="specify presets to run with. Allows all if no preset names are specified.",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -107,27 +87,22 @@ def run_generator(generator_name, test_providers: Iterable[TestProvider]):
|
||||
log_file = Path(output_dir) / 'testgen_error_log.txt'
|
||||
|
||||
print(f"Generating tests into {output_dir}")
|
||||
print(f"Reading configs from {args.configs_path}")
|
||||
print(f'Error log file: {log_file}')
|
||||
|
||||
configs = args.config_list
|
||||
if configs is None:
|
||||
configs = []
|
||||
presets = args.preset_list
|
||||
if presets is None:
|
||||
presets = []
|
||||
|
||||
if len(configs) != 0:
|
||||
print(f"Filtering test-generator runs to only include configs: {', '.join(configs)}")
|
||||
if len(presets) != 0:
|
||||
print(f"Filtering test-generator runs to only include presets: {', '.join(presets)}")
|
||||
|
||||
for tprov in test_providers:
|
||||
# loads configuration etc.
|
||||
config_name = tprov.prepare(args.configs_path)
|
||||
if len(configs) != 0 and config_name not in configs:
|
||||
print(f"skipping tests with config '{config_name}' since it is filtered out")
|
||||
continue
|
||||
# runs anything that we don't want to repeat for every test case.
|
||||
tprov.prepare()
|
||||
|
||||
print(f"generating tests with config '{config_name}' ...")
|
||||
for test_case in tprov.make_cases():
|
||||
case_dir = (
|
||||
Path(output_dir) / Path(config_name) / Path(test_case.fork_name)
|
||||
Path(output_dir) / Path(test_case.preset_name) / Path(test_case.fork_name)
|
||||
/ Path(test_case.runner_name) / Path(test_case.handler_name)
|
||||
/ Path(test_case.suite_name) / Path(test_case.case_name)
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@ TestCasePart = NewType("TestCasePart", Tuple[str, str, Any])
|
||||
@dataclass
|
||||
class TestCase(object):
|
||||
fork_name: str
|
||||
preset_name: str
|
||||
runner_name: str
|
||||
handler_name: str
|
||||
suite_name: str
|
||||
@@ -28,8 +29,7 @@ class TestCase(object):
|
||||
|
||||
@dataclass
|
||||
class TestProvider(object):
|
||||
# Prepares the context with a configuration, loaded from the given config path.
|
||||
# fn(config path) => chosen config name
|
||||
prepare: Callable[[str], str]
|
||||
# Prepares the context for the provider as a whole, as opposed to per-test-case changes.
|
||||
prepare: Callable[[], None]
|
||||
# Retrieves an iterable of cases, called after prepare()
|
||||
make_cases: Callable[[], Iterable[TestCase]]
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
from importlib import reload, import_module
|
||||
from importlib import import_module
|
||||
from inspect import getmembers, isfunction
|
||||
from typing import Any, Callable, Dict, Iterable, Optional
|
||||
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.test.helpers.constants import ALL_CONFIGS, TESTGEN_FORKS
|
||||
from eth2spec.test.helpers.typing import SpecForkName, ConfigName
|
||||
from eth2spec.test.helpers.constants import ALL_PRESETS, TESTGEN_FORKS
|
||||
from eth2spec.test.helpers.typing import SpecForkName, PresetBaseName
|
||||
|
||||
from eth2spec.gen_helpers.gen_base import gen_runner
|
||||
from eth2spec.gen_helpers.gen_base.gen_typing import TestCase, TestProvider
|
||||
|
||||
|
||||
def generate_from_tests(runner_name: str, handler_name: str, src: Any,
|
||||
fork_name: SpecForkName, bls_active: bool = True,
|
||||
fork_name: SpecForkName, preset_name: PresetBaseName,
|
||||
bls_active: bool = True,
|
||||
phase: Optional[str]=None) -> Iterable[TestCase]:
|
||||
"""
|
||||
Generate a list of test cases by running tests from the given src in generator-mode.
|
||||
@@ -21,8 +21,10 @@ def generate_from_tests(runner_name: str, handler_name: str, src: Any,
|
||||
:param src: to retrieve tests from (discovered using inspect.getmembers).
|
||||
:param fork_name: the folder name for these tests.
|
||||
(if multiple forks are applicable, indicate the last fork)
|
||||
:param preset_name: to select a preset. Tests that do not support the preset will be skipped.
|
||||
:param bls_active: optional, to override BLS switch preference. Defaults to True.
|
||||
:param phase: optional, to run tests against a particular spec version. Default to `fork_name` value.
|
||||
Set to the pre-fork (w.r.t. fork_name) in multi-fork tests.
|
||||
:return: an iterable of test cases.
|
||||
"""
|
||||
fn_names = [
|
||||
@@ -44,40 +46,36 @@ def generate_from_tests(runner_name: str, handler_name: str, src: Any,
|
||||
|
||||
yield TestCase(
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
runner_name=runner_name,
|
||||
handler_name=handler_name,
|
||||
suite_name='pyspec_tests',
|
||||
case_name=case_name,
|
||||
# TODO: with_all_phases and other per-phase tooling, should be replaced with per-fork equivalent.
|
||||
case_fn=lambda: tfn(generator_mode=True, phase=phase, bls_active=bls_active)
|
||||
case_fn=lambda: tfn(generator_mode=True, phase=phase, preset=preset_name, bls_active=bls_active)
|
||||
)
|
||||
|
||||
|
||||
def get_provider(create_provider_fn: Callable[[SpecForkName, str, str, ConfigName], TestProvider],
|
||||
config_name: ConfigName,
|
||||
def get_provider(create_provider_fn: Callable[[SpecForkName, PresetBaseName, str, str], TestProvider],
|
||||
fork_name: SpecForkName,
|
||||
preset_name: PresetBaseName,
|
||||
all_mods: Dict[str, Dict[str, str]]) -> Iterable[TestProvider]:
|
||||
for key, mod_name in all_mods[fork_name].items():
|
||||
yield create_provider_fn(
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
handler_name=key,
|
||||
tests_src_mod_name=mod_name,
|
||||
config_name=config_name,
|
||||
)
|
||||
|
||||
|
||||
def get_create_provider_fn(
|
||||
runner_name: str, config_name: ConfigName, specs: Iterable[Any]
|
||||
) -> Callable[[SpecForkName, str, str, ConfigName], TestProvider]:
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
config_util.prepare_config(configs_path, config_name)
|
||||
for spec in specs:
|
||||
reload(spec)
|
||||
def get_create_provider_fn(runner_name: str) -> Callable[[SpecForkName, str, str, PresetBaseName], TestProvider]:
|
||||
def prepare_fn() -> None:
|
||||
bls.use_milagro()
|
||||
return config_name
|
||||
return
|
||||
|
||||
def create_provider(fork_name: SpecForkName, handler_name: str,
|
||||
tests_src_mod_name: str, config_name: ConfigName) -> TestProvider:
|
||||
def create_provider(fork_name: SpecForkName, preset_name: PresetBaseName,
|
||||
handler_name: str, tests_src_mod_name: str) -> TestProvider:
|
||||
def cases_fn() -> Iterable[TestCase]:
|
||||
tests_src = import_module(tests_src_mod_name)
|
||||
return generate_from_tests(
|
||||
@@ -85,22 +83,26 @@ def get_create_provider_fn(
|
||||
handler_name=handler_name,
|
||||
src=tests_src,
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
)
|
||||
|
||||
return TestProvider(prepare=prepare_fn, make_cases=cases_fn)
|
||||
return create_provider
|
||||
|
||||
|
||||
def run_state_test_generators(runner_name: str, specs: Iterable[Any], all_mods: Dict[str, Dict[str, str]]) -> None:
|
||||
def run_state_test_generators(runner_name: str,
|
||||
all_mods: Dict[str, Dict[str, str]],
|
||||
presets: Iterable[PresetBaseName] = ALL_PRESETS,
|
||||
forks: Iterable[SpecForkName] = TESTGEN_FORKS) -> None:
|
||||
"""
|
||||
Generate all available state tests of `TESTGEN_FORKS` forks of `ALL_CONFIGS` configs of the given runner.
|
||||
Generate all available state tests of `TESTGEN_FORKS` forks of `ALL_PRESETS` presets of the given runner.
|
||||
"""
|
||||
for config_name in ALL_CONFIGS:
|
||||
for fork_name in TESTGEN_FORKS:
|
||||
for preset_name in presets:
|
||||
for fork_name in forks:
|
||||
if fork_name in all_mods:
|
||||
gen_runner.run_generator(runner_name, get_provider(
|
||||
create_provider_fn=get_create_provider_fn(runner_name, config_name, specs),
|
||||
config_name=config_name,
|
||||
create_provider_fn=get_create_provider_fn(runner_name),
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
all_mods=all_mods,
|
||||
))
|
||||
|
||||
@@ -17,7 +17,7 @@ from eth2spec.test.helpers.sync_committee import (
|
||||
from eth2spec.test.context import (
|
||||
expect_assertion_error,
|
||||
with_altair_and_later,
|
||||
with_configs,
|
||||
with_presets,
|
||||
spec_state_test,
|
||||
always_bls,
|
||||
)
|
||||
@@ -213,7 +213,7 @@ def run_successful_sync_committee_test(spec, state, committee_indices, committee
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="to create nonduplicate committee")
|
||||
@with_presets([MINIMAL], reason="to create nonduplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=False)
|
||||
@@ -229,7 +229,7 @@ def test_sync_committee_rewards_nonduplicate_committee(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_configs([MAINNET], reason="to create duplicate committee")
|
||||
@with_presets([MAINNET], reason="to create duplicate committee")
|
||||
@spec_state_test
|
||||
def test_sync_committee_rewards_duplicate_committee(spec, state):
|
||||
committee_indices = get_committee_indices(spec, state, duplicates=True)
|
||||
@@ -305,7 +305,7 @@ def test_invalid_signature_past_block(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="to produce different committee sets")
|
||||
@with_presets([MINIMAL], reason="to produce different committee sets")
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_invalid_signature_previous_committee(spec, state):
|
||||
@@ -343,7 +343,7 @@ def test_invalid_signature_previous_committee(spec, state):
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_valid_signature_future_committee(spec, state):
|
||||
# NOTE: the `state` provided is at genesis and the process to select
|
||||
# sync committees currently returns the same committee for the first and second
|
||||
|
||||
@@ -3,7 +3,7 @@ from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
spec_test,
|
||||
with_altair_and_later,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_custom_state,
|
||||
single_phase,
|
||||
misc_balances,
|
||||
@@ -48,7 +48,7 @@ def run_sync_committees_progress_test(spec, state):
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_sync_committees_progress_genesis(spec, state):
|
||||
# Genesis epoch period has an exceptional case
|
||||
assert spec.get_current_epoch(state) == spec.GENESIS_EPOCH
|
||||
@@ -59,7 +59,7 @@ def test_sync_committees_progress_genesis(spec, state):
|
||||
@with_altair_and_later
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_sync_committees_progress_not_genesis(spec, state):
|
||||
# Transition out of the genesis epoch period to test non-exceptional case
|
||||
assert spec.get_current_epoch(state) == spec.GENESIS_EPOCH
|
||||
@@ -70,10 +70,10 @@ def test_sync_committees_progress_not_genesis(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
@always_bls
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_sync_committees_progress_misc_balances(spec, state):
|
||||
yield from run_sync_committees_progress_test(spec, state)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from eth2spec.test.context import (
|
||||
with_phases,
|
||||
with_custom_state,
|
||||
with_configs,
|
||||
with_presets,
|
||||
spec_test, with_state,
|
||||
low_balances, misc_balances, large_validator_set,
|
||||
)
|
||||
@@ -57,7 +57,7 @@ def test_fork_many_next_epoch(spec, phases, state):
|
||||
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_fork_random_low_balances(spec, phases, state):
|
||||
@@ -65,7 +65,7 @@ def test_fork_random_low_balances(spec, phases, state):
|
||||
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_fork_random_misc_balances(spec, phases, state):
|
||||
@@ -73,9 +73,9 @@ def test_fork_random_misc_balances(spec, phases, state):
|
||||
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@with_configs([MINIMAL],
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_fork_random_large_validator_set(spec, phases, state):
|
||||
|
||||
@@ -3,7 +3,7 @@ from random import Random
|
||||
from eth2spec.test.context import (
|
||||
with_phases,
|
||||
with_custom_state,
|
||||
with_configs,
|
||||
with_presets,
|
||||
spec_test, with_state,
|
||||
low_balances, misc_balances, large_validator_set,
|
||||
)
|
||||
@@ -93,7 +93,7 @@ def test_altair_fork_random_mismatched_attestations(spec, phases, state):
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_altair_fork_random_low_balances(spec, phases, state):
|
||||
randomize_state(spec, state, rng=Random(5050))
|
||||
@@ -102,7 +102,7 @@ def test_altair_fork_random_low_balances(spec, phases, state):
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_altair_fork_random_misc_balances(spec, phases, state):
|
||||
randomize_state(spec, state, rng=Random(6060))
|
||||
@@ -110,10 +110,10 @@ def test_altair_fork_random_misc_balances(spec, phases, state):
|
||||
|
||||
|
||||
@with_phases(phases=[PHASE0], other_phases=[ALTAIR])
|
||||
@with_configs([MINIMAL],
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@with_meta_tags(ALTAIR_FORK_TEST_META_TAGS)
|
||||
def test_altair_fork_random_large_validator_set(spec, phases, state):
|
||||
randomize_state(spec, state, rng=Random(7070))
|
||||
|
||||
@@ -45,7 +45,7 @@ def test_random_high_inactivity_scores(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_random_inactivity_scores_low_balances_0(spec, state):
|
||||
@@ -54,7 +54,7 @@ def test_random_inactivity_scores_low_balances_0(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_random_inactivity_scores_low_balances_1(spec, state):
|
||||
@@ -63,7 +63,7 @@ def test_random_inactivity_scores_low_balances_1(spec, state):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_full_random_misc_balances(spec, state):
|
||||
|
||||
@@ -98,4 +98,4 @@ def test_inactivity_scores(spec, state):
|
||||
yield 'post', state
|
||||
|
||||
for pre, post in zip(previous_inactivity_scores, state.inactivity_scores):
|
||||
assert post == pre + spec.INACTIVITY_SCORE_BIAS
|
||||
assert post == pre + spec.config.INACTIVITY_SCORE_BIAS
|
||||
|
||||
@@ -69,8 +69,8 @@ def _do_altair_fork(state, spec, post_spec, fork_epoch, with_block=True):
|
||||
state = post_spec.upgrade_to_altair(state)
|
||||
|
||||
assert state.fork.epoch == fork_epoch
|
||||
assert state.fork.previous_version == post_spec.GENESIS_FORK_VERSION
|
||||
assert state.fork.current_version == post_spec.ALTAIR_FORK_VERSION
|
||||
assert state.fork.previous_version == post_spec.config.GENESIS_FORK_VERSION
|
||||
assert state.fork.current_version == post_spec.config.ALTAIR_FORK_VERSION
|
||||
|
||||
if with_block:
|
||||
return state, _state_transition_and_sign_block_at_slot(post_spec, state)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from eth2spec.test.context import spec_configured_state_test, with_phases
|
||||
from eth2spec.test.helpers.constants import ALTAIR
|
||||
|
||||
|
||||
@with_phases([ALTAIR])
|
||||
@spec_configured_state_test({
|
||||
'GENESIS_FORK_VERSION': '0x12345678',
|
||||
'ALTAIR_FORK_VERSION': '0x11111111',
|
||||
'ALTAIR_FORK_EPOCH': 4
|
||||
})
|
||||
def test_config_override(spec, state):
|
||||
assert spec.config.ALTAIR_FORK_EPOCH == 4
|
||||
assert spec.config.GENESIS_FORK_VERSION != spec.Version('0x00000000')
|
||||
assert spec.config.GENESIS_FORK_VERSION == spec.Version('0x12345678')
|
||||
assert spec.config.ALTAIR_FORK_VERSION == spec.Version('0x11111111')
|
||||
assert state.fork.current_version == spec.Version('0x11111111')
|
||||
# TODO: it would be nice if the create_genesis_state actually outputs a state
|
||||
# for the fork with a slot that matches at least the fork boundary.
|
||||
# assert spec.get_current_epoch(state) >= 4
|
||||
@@ -1,6 +1,6 @@
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_phases,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import next_epoch_with_attestations
|
||||
@@ -83,7 +83,7 @@ def test_process_light_client_update_not_updated(spec, state):
|
||||
|
||||
@with_phases([ALTAIR])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_process_light_client_update_timeout(spec, state):
|
||||
pre_snapshot = spec.LightClientSnapshot(
|
||||
header=spec.BeaconBlockHeader(),
|
||||
@@ -149,7 +149,7 @@ def test_process_light_client_update_timeout(spec, state):
|
||||
|
||||
@with_phases([ALTAIR])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_process_light_client_update_finality_updated(spec, state):
|
||||
pre_snapshot = spec.LightClientSnapshot(
|
||||
header=spec.BeaconBlockHeader(),
|
||||
|
||||
@@ -8,7 +8,7 @@ from eth2spec.utils import bls
|
||||
from eth2spec.utils.bls import only_with_bls
|
||||
from eth2spec.test.context import (
|
||||
with_altair_and_later,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_state,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
@@ -95,7 +95,7 @@ def _get_sync_committee_signature(
|
||||
|
||||
@only_with_bls()
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
@with_state
|
||||
def test_process_sync_committee_contributions(phases, spec, state):
|
||||
# skip over slots at genesis
|
||||
@@ -157,7 +157,7 @@ def _get_expected_subnets_by_pubkey(sync_committee_members):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
@with_state
|
||||
def test_compute_subnets_for_sync_committee(state, spec, phases):
|
||||
# Transition to the head of the next period
|
||||
@@ -186,7 +186,7 @@ def test_compute_subnets_for_sync_committee(state, spec, phases):
|
||||
|
||||
|
||||
@with_altair_and_later
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
@with_state
|
||||
def test_compute_subnets_for_sync_committee_slot_period_boundary(state, spec, phases):
|
||||
# Transition to the end of the period
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.test import context
|
||||
from eth2spec.utils import bls as bls_utils
|
||||
|
||||
@@ -27,8 +26,8 @@ def fixture(*args, **kwargs):
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--config", action="store", type=str, default="minimal",
|
||||
help="config: make the pyspec use the specified configuration"
|
||||
"--preset", action="store", type=str, default="minimal",
|
||||
help="preset: make the pyspec use the specified preset"
|
||||
)
|
||||
parser.addoption(
|
||||
"--disable-bls", action="store_true", default=False,
|
||||
@@ -41,11 +40,8 @@ def pytest_addoption(parser):
|
||||
|
||||
|
||||
@fixture(autouse=True)
|
||||
def config(request):
|
||||
config_name = request.config.getoption("--config")
|
||||
config_util.prepare_config('../../../configs/', config_name)
|
||||
# now that the presets are loaded, reload the specs to apply them
|
||||
context.reload_specs()
|
||||
def preset(request):
|
||||
context.DEFAULT_TEST_PRESET = request.config.getoption("--preset")
|
||||
|
||||
|
||||
@fixture(autouse=True)
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import pytest
|
||||
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from copy import deepcopy
|
||||
from eth2spec.phase0 import mainnet as spec_phase0_mainnet, minimal as spec_phase0_minimal
|
||||
from eth2spec.altair import mainnet as spec_altair_mainnet, minimal as spec_altair_minimal
|
||||
from eth2spec.merge import mainnet as spec_merge_mainnet, minimal as spec_merge_minimal
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR, MERGE,
|
||||
SpecForkName, PresetBaseName,
|
||||
PHASE0, ALTAIR, MERGE, MINIMAL, MAINNET,
|
||||
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_MERGE,
|
||||
)
|
||||
from .helpers.genesis import create_genesis_state
|
||||
from .utils import vector_test, with_meta_tags, build_transition_test
|
||||
|
||||
from random import Random
|
||||
from typing import Any, Callable, Sequence, TypedDict, Protocol
|
||||
from typing import Any, Callable, Sequence, TypedDict, Protocol, Dict
|
||||
|
||||
from lru import LRU
|
||||
|
||||
from importlib import reload
|
||||
|
||||
|
||||
def reload_specs():
|
||||
reload(spec_phase0)
|
||||
reload(spec_altair)
|
||||
reload(spec_merge)
|
||||
# Without pytest CLI arg or pyspec-test-generator 'preset' argument, this will be the config to apply.
|
||||
DEFAULT_TEST_PRESET = MINIMAL
|
||||
|
||||
|
||||
# TODO: currently phases are defined as python modules.
|
||||
# It would be better if they would be more well-defined interfaces for stronger typing.
|
||||
|
||||
class Configuration(Protocol):
|
||||
PRESET_BASE: str
|
||||
|
||||
|
||||
class Spec(Protocol):
|
||||
version: str
|
||||
fork: str
|
||||
config: Configuration
|
||||
|
||||
|
||||
class SpecPhase0(Spec):
|
||||
@@ -47,6 +47,20 @@ class SpecMerge(Spec):
|
||||
...
|
||||
|
||||
|
||||
spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
||||
MINIMAL: {
|
||||
PHASE0: spec_phase0_minimal,
|
||||
ALTAIR: spec_altair_minimal,
|
||||
MERGE: spec_merge_minimal,
|
||||
},
|
||||
MAINNET: {
|
||||
PHASE0: spec_phase0_mainnet,
|
||||
ALTAIR: spec_altair_mainnet,
|
||||
MERGE: spec_merge_mainnet,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class SpecForks(TypedDict, total=False):
|
||||
PHASE0: SpecPhase0
|
||||
ALTAIR: SpecAltair
|
||||
@@ -71,8 +85,8 @@ def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
|
||||
def deco(fn):
|
||||
|
||||
def entry(*args, spec: Spec, phases: SpecForks, **kw):
|
||||
# make a key for the state
|
||||
key = (spec.fork, spec.CONFIG_NAME, spec.__file__, balances_fn, threshold_fn)
|
||||
# make a key for the state, unique to the fork + config (incl preset choice) and balances/activations
|
||||
key = (spec.fork, spec.config.__hash__(), spec.__file__, balances_fn, threshold_fn)
|
||||
global _custom_state_cache_dict
|
||||
if key not in _custom_state_cache_dict:
|
||||
state = _prepare_state(balances_fn, threshold_fn, spec, phases)
|
||||
@@ -204,6 +218,14 @@ def spec_state_test(fn):
|
||||
return spec_test(with_state(single_phase(fn)))
|
||||
|
||||
|
||||
def spec_configured_state_test(conf):
|
||||
overrides = with_config_overrides(conf)
|
||||
|
||||
def decorator(fn):
|
||||
return spec_test(overrides(with_state(single_phase(fn))))
|
||||
return decorator
|
||||
|
||||
|
||||
def expect_assertion_error(fn):
|
||||
bad = False
|
||||
try:
|
||||
@@ -320,6 +342,11 @@ def with_phases(phases, other_phases=None):
|
||||
if other_phases is not None:
|
||||
available_phases |= set(other_phases)
|
||||
|
||||
preset_name = DEFAULT_TEST_PRESET
|
||||
if 'preset' in kw:
|
||||
preset_name = kw.pop('preset')
|
||||
targets = spec_targets[preset_name]
|
||||
|
||||
# TODO: test state is dependent on phase0 but is immediately transitioned to later phases.
|
||||
# A new state-creation helper for later phases may be in place, and then tests can run without phase0
|
||||
available_phases.add(PHASE0)
|
||||
@@ -327,20 +354,20 @@ def with_phases(phases, other_phases=None):
|
||||
# Populate all phases for multi-phase tests
|
||||
phase_dir = {}
|
||||
if PHASE0 in available_phases:
|
||||
phase_dir[PHASE0] = spec_phase0
|
||||
phase_dir[PHASE0] = targets[PHASE0]
|
||||
if ALTAIR in available_phases:
|
||||
phase_dir[ALTAIR] = spec_altair
|
||||
phase_dir[ALTAIR] = targets[ALTAIR]
|
||||
if MERGE in available_phases:
|
||||
phase_dir[MERGE] = spec_merge
|
||||
phase_dir[MERGE] = targets[MERGE]
|
||||
|
||||
# return is ignored whenever multiple phases are ran.
|
||||
# This return is for test generators to emit python generators (yielding test vector outputs)
|
||||
if PHASE0 in run_phases:
|
||||
ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw)
|
||||
ret = fn(spec=targets[PHASE0], phases=phase_dir, *args, **kw)
|
||||
if ALTAIR in run_phases:
|
||||
ret = fn(spec=spec_altair, phases=phase_dir, *args, **kw)
|
||||
ret = fn(spec=targets[ALTAIR], phases=phase_dir, *args, **kw)
|
||||
if MERGE in run_phases:
|
||||
ret = fn(spec=spec_merge, phases=phase_dir, *args, **kw)
|
||||
ret = fn(spec=targets[MERGE], phases=phase_dir, *args, **kw)
|
||||
|
||||
# TODO: merge, sharding, custody_game and das are not executable yet.
|
||||
# Tests that specify these features will not run, and get ignored for these specific phases.
|
||||
@@ -349,12 +376,13 @@ def with_phases(phases, other_phases=None):
|
||||
return decorator
|
||||
|
||||
|
||||
def with_configs(configs, reason=None):
|
||||
def with_presets(preset_bases, reason=None):
|
||||
available_presets = set(preset_bases)
|
||||
|
||||
def decorator(fn):
|
||||
def wrapper(*args, spec: Spec, **kw):
|
||||
available_configs = set(configs)
|
||||
if spec.CONFIG_NAME not in available_configs:
|
||||
message = f"doesn't support this config: {spec.CONFIG_NAME}."
|
||||
if spec.config.PRESET_BASE not in available_presets:
|
||||
message = f"doesn't support this preset base: {spec.config.PRESET_BASE}."
|
||||
if reason is not None:
|
||||
message = f"{message} Reason: {reason}"
|
||||
dump_skipping_message(message)
|
||||
@@ -365,6 +393,45 @@ def with_configs(configs, reason=None):
|
||||
return decorator
|
||||
|
||||
|
||||
def with_config_overrides(config_overrides):
|
||||
"""
|
||||
WARNING: the spec_test decorator must wrap this, to ensure the decorated test actually runs.
|
||||
This decorator forces the test to yield, and pytest doesn't run generator tests, and instead silently passes it.
|
||||
Use 'spec_configured_state_test' instead of 'spec_state_test' if you are unsure.
|
||||
|
||||
This is a decorator that applies a dict of config value overrides to the spec during execution.
|
||||
"""
|
||||
def decorator(fn):
|
||||
def wrapper(*args, spec: Spec, **kw):
|
||||
# remember the old config
|
||||
old_config = spec.config
|
||||
|
||||
# apply our overrides to a copy of it, and apply it to the spec
|
||||
tmp_config = deepcopy(old_config._asdict()) # not a private method, there are multiple
|
||||
tmp_config.update(config_overrides)
|
||||
config_types = spec.Configuration.__annotations__
|
||||
# Retain types of all config values
|
||||
test_config = {k: config_types[k](v) for k, v in tmp_config.items()}
|
||||
|
||||
# Output the config for test vectors (TODO: check config YAML encoding)
|
||||
yield 'config', 'data', test_config
|
||||
|
||||
spec.config = spec.Configuration(**test_config)
|
||||
|
||||
# Run the function
|
||||
out = fn(*args, spec=spec, **kw)
|
||||
# If it's not returning None like a normal test function,
|
||||
# it's generating things, and we need to complete it before setting back the config.
|
||||
if out is not None:
|
||||
yield from out
|
||||
|
||||
# Restore the old config and apply it
|
||||
spec.config = old_config
|
||||
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def is_post_altair(spec):
|
||||
if spec.fork == MERGE: # TODO: remove parallel Altair-Merge condition after rebase.
|
||||
return False
|
||||
|
||||
@@ -16,7 +16,7 @@ from eth2spec.test.context import (
|
||||
disable_process_reveal_deadlines,
|
||||
spec_state_test,
|
||||
with_phases,
|
||||
with_configs,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
|
||||
@@ -72,7 +72,7 @@ def run_custody_chunk_response_processing(spec, state, custody_response, valid=T
|
||||
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
@disable_process_reveal_deadlines
|
||||
def test_challenge_appended(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
@@ -97,7 +97,7 @@ def test_challenge_appended(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_challenge_empty_element_replaced(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1
|
||||
@@ -123,7 +123,7 @@ def test_challenge_empty_element_replaced(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_duplicate_challenge(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1
|
||||
@@ -149,7 +149,7 @@ def test_duplicate_challenge(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_second_challenge(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1
|
||||
@@ -177,7 +177,7 @@ def test_second_challenge(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_multiple_epochs_custody(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3)
|
||||
@@ -202,7 +202,7 @@ def test_multiple_epochs_custody(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_many_epochs_custody(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20)
|
||||
@@ -227,7 +227,7 @@ def test_many_epochs_custody(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_off_chain_attestation(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
@@ -248,7 +248,7 @@ def test_off_chain_attestation(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_custody_response(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
@@ -280,7 +280,7 @@ def test_custody_response(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_custody_response_chunk_index_2(spec, state):
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
|
||||
@@ -311,7 +311,7 @@ def test_custody_response_chunk_index_2(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_custody_response_multiple_epochs(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3)
|
||||
@@ -343,7 +343,7 @@ def test_custody_response_multiple_epochs(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_custody_response_many_epochs(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20)
|
||||
|
||||
@@ -17,7 +17,7 @@ from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
disable_process_reveal_deadlines,
|
||||
with_configs,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
|
||||
@@ -117,7 +117,7 @@ def run_standard_custody_slashing_test(spec,
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state)
|
||||
|
||||
@@ -125,7 +125,7 @@ def test_custody_slashing(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_incorrect_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state, correct=False)
|
||||
|
||||
@@ -133,7 +133,7 @@ def test_incorrect_custody_slashing(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_multiple_epochs_custody(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 3)
|
||||
|
||||
@@ -141,7 +141,7 @@ def test_multiple_epochs_custody(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_many_epochs_custody(spec, state):
|
||||
yield from run_standard_custody_slashing_test(spec, state, shard_lateness=spec.SLOTS_PER_EPOCH * 5)
|
||||
|
||||
@@ -149,7 +149,7 @@ def test_many_epochs_custody(spec, state):
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@disable_process_reveal_deadlines
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_invalid_custody_slashing(spec, state):
|
||||
yield from run_standard_custody_slashing_test(
|
||||
spec,
|
||||
|
||||
@@ -9,7 +9,7 @@ from eth2spec.test.helpers.state import transition_to, transition_to_valid_shard
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
with_phases,
|
||||
with_configs,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.phase0.block_processing.test_process_attestation import run_attestation_processing
|
||||
from eth2spec.test.helpers.constants import (
|
||||
@@ -29,7 +29,7 @@ def run_process_challenge_deadlines(spec, state):
|
||||
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_validator_slashed_after_chunk_challenge(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1
|
||||
|
||||
@@ -4,7 +4,7 @@ from eth2spec.test.helpers.custody import (
|
||||
from eth2spec.test.helpers.state import transition_to
|
||||
from eth2spec.test.context import (
|
||||
with_phases,
|
||||
with_configs,
|
||||
with_presets,
|
||||
spec_state_test,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import (
|
||||
@@ -23,7 +23,7 @@ def run_process_challenge_deadlines(spec, state):
|
||||
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_validator_slashed_after_reveal_deadline(spec, state):
|
||||
assert state.validators[0].slashed == 0
|
||||
transition_to(spec, state, spec.get_randao_epoch_for_custody_period(0, 0) * spec.SLOTS_PER_EPOCH)
|
||||
@@ -43,7 +43,7 @@ def test_validator_slashed_after_reveal_deadline(spec, state):
|
||||
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_validator_not_slashed_after_reveal(spec, state):
|
||||
transition_to(spec, state, spec.EPOCHS_PER_CUSTODY_PERIOD * spec.SLOTS_PER_EPOCH)
|
||||
custody_key_reveal = get_valid_custody_key_reveal(spec, state)
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import Dict, Sequence
|
||||
from eth2spec.test.context import (
|
||||
with_phases,
|
||||
spec_state_test,
|
||||
with_configs,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import get_valid_on_time_attestation
|
||||
from eth2spec.test.helpers.block import build_empty_block
|
||||
@@ -83,7 +83,7 @@ def test_with_shard_transition_with_custody_challenge_and_response(spec, state):
|
||||
|
||||
@with_phases([CUSTODY_GAME])
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL])
|
||||
@with_presets([MINIMAL])
|
||||
def test_custody_key_reveal(spec, state):
|
||||
transition_to_valid_shard_slot(spec, state)
|
||||
transition_to(spec, state, state.slot + spec.EPOCHS_PER_CUSTODY_PERIOD * spec.SLOTS_PER_EPOCH)
|
||||
|
||||
@@ -36,7 +36,7 @@ def run_fork_test(post_spec, pre_state):
|
||||
assert getattr(pre_state, field) != getattr(post_state, field)
|
||||
|
||||
assert pre_state.fork.current_version == post_state.fork.previous_version
|
||||
assert post_state.fork.current_version == post_spec.ALTAIR_FORK_VERSION
|
||||
assert post_state.fork.current_version == post_spec.config.ALTAIR_FORK_VERSION
|
||||
assert post_state.fork.epoch == post_spec.get_current_epoch(post_state)
|
||||
|
||||
yield 'post', post_state
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .typing import SpecForkName, ConfigName
|
||||
from .typing import SpecForkName, PresetBaseName
|
||||
|
||||
|
||||
#
|
||||
@@ -28,7 +28,7 @@ FORKS_BEFORE_MERGE = (PHASE0,)
|
||||
#
|
||||
# Config
|
||||
#
|
||||
MAINNET = ConfigName('mainnet')
|
||||
MINIMAL = ConfigName('minimal')
|
||||
MAINNET = PresetBaseName('mainnet')
|
||||
MINIMAL = PresetBaseName('minimal')
|
||||
|
||||
ALL_CONFIGS = (MINIMAL, MAINNET)
|
||||
ALL_PRESETS = (MINIMAL, MAINNET)
|
||||
|
||||
@@ -10,7 +10,7 @@ def get_anchor_root(spec, state):
|
||||
|
||||
def add_block_to_store(spec, store, signed_block):
|
||||
pre_state = store.block_states[signed_block.message.parent_root]
|
||||
block_time = pre_state.genesis_time + signed_block.message.slot * spec.SECONDS_PER_SLOT
|
||||
block_time = pre_state.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT
|
||||
|
||||
if store.time < block_time:
|
||||
spec.on_tick(store, block_time)
|
||||
@@ -23,7 +23,7 @@ def tick_and_run_on_block(spec, store, signed_block, test_steps=None):
|
||||
test_steps = []
|
||||
|
||||
pre_state = store.block_states[signed_block.message.parent_root]
|
||||
block_time = pre_state.genesis_time + signed_block.message.slot * spec.SECONDS_PER_SLOT
|
||||
block_time = pre_state.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT
|
||||
|
||||
if store.time < block_time:
|
||||
on_tick_and_append_step(spec, store, block_time, test_steps)
|
||||
@@ -37,8 +37,8 @@ def tick_and_run_on_attestation(spec, store, attestation, test_steps=None):
|
||||
|
||||
parent_block = store.blocks[attestation.data.beacon_block_root]
|
||||
pre_state = store.block_states[spec.hash_tree_root(parent_block)]
|
||||
block_time = pre_state.genesis_time + parent_block.slot * spec.SECONDS_PER_SLOT
|
||||
next_epoch_time = block_time + spec.SLOTS_PER_EPOCH * spec.SECONDS_PER_SLOT
|
||||
block_time = pre_state.genesis_time + parent_block.slot * spec.config.SECONDS_PER_SLOT
|
||||
next_epoch_time = block_time + spec.SLOTS_PER_EPOCH * spec.config.SECONDS_PER_SLOT
|
||||
|
||||
if store.time < next_epoch_time:
|
||||
spec.on_tick(store, next_epoch_time)
|
||||
|
||||
@@ -25,12 +25,12 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
|
||||
deposit_root = b'\x42' * 32
|
||||
|
||||
eth1_block_hash = b'\xda' * 32
|
||||
current_version = spec.GENESIS_FORK_VERSION
|
||||
current_version = spec.config.GENESIS_FORK_VERSION
|
||||
|
||||
if spec.fork == ALTAIR:
|
||||
current_version = spec.ALTAIR_FORK_VERSION
|
||||
current_version = spec.config.ALTAIR_FORK_VERSION
|
||||
elif spec.fork == MERGE:
|
||||
current_version = spec.MERGE_FORK_VERSION
|
||||
current_version = spec.config.MERGE_FORK_VERSION
|
||||
|
||||
state = spec.BeaconState(
|
||||
genesis_time=0,
|
||||
@@ -41,7 +41,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold):
|
||||
block_hash=eth1_block_hash,
|
||||
),
|
||||
fork=spec.Fork(
|
||||
previous_version=spec.GENESIS_FORK_VERSION,
|
||||
previous_version=spec.config.GENESIS_FORK_VERSION,
|
||||
current_version=current_version,
|
||||
epoch=spec.GENESIS_EPOCH,
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from eth2spec.phase0 import spec
|
||||
|
||||
privkeys = [i + 1 for i in range(spec.SLOTS_PER_EPOCH * 256)]
|
||||
# Enough keys for 256 validators per slot in worst-case epoch length
|
||||
privkeys = [i + 1 for i in range(32 * 256)]
|
||||
pubkeys = [bls.SkToPk(privkey) for privkey in privkeys]
|
||||
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}
|
||||
|
||||
@@ -19,7 +19,7 @@ def run_slash_and_exit(spec, state, slash_index, exit_index, valid=True):
|
||||
Helper function to run a test that slashes and exits two validators
|
||||
"""
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
@@ -127,7 +127,7 @@ def get_random_voluntary_exits(spec, state, to_be_slashed_indices, rng):
|
||||
|
||||
def run_test_full_random_operations(spec, state, rng=Random(2080)):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
# prepare state for deposits before building block
|
||||
deposits = prepare_state_and_get_random_deposits(spec, state, rng)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from random import Random
|
||||
from lru import LRU
|
||||
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.phase0.mainnet import VALIDATOR_REGISTRY_LIMIT # equal everywhere, fine to import
|
||||
from eth2spec.test.context import is_post_altair
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch,
|
||||
@@ -17,8 +17,8 @@ from eth2spec.utils.ssz.ssz_typing import Container, uint64, List
|
||||
|
||||
|
||||
class Deltas(Container):
|
||||
rewards: List[uint64, spec_phase0.VALIDATOR_REGISTRY_LIMIT]
|
||||
penalties: List[uint64, spec_phase0.VALIDATOR_REGISTRY_LIMIT]
|
||||
rewards: List[uint64, VALIDATOR_REGISTRY_LIMIT]
|
||||
penalties: List[uint64, VALIDATOR_REGISTRY_LIMIT]
|
||||
|
||||
|
||||
def has_enough_for_reward(spec, state, index):
|
||||
@@ -45,7 +45,7 @@ def has_enough_for_leak_penalty(spec, state, index):
|
||||
if is_post_altair(spec):
|
||||
return (
|
||||
state.validators[index].effective_balance * state.inactivity_scores[index]
|
||||
> spec.INACTIVITY_SCORE_BIAS * spec.INACTIVITY_PENALTY_QUOTIENT_ALTAIR
|
||||
> spec.config.INACTIVITY_SCORE_BIAS * spec.INACTIVITY_PENALTY_QUOTIENT_ALTAIR
|
||||
)
|
||||
else:
|
||||
return (
|
||||
|
||||
@@ -42,10 +42,10 @@ def transition_to_slot_via_block(spec, state, slot):
|
||||
|
||||
def transition_to_valid_shard_slot(spec, state):
|
||||
"""
|
||||
Transition to slot `compute_epoch_at_slot(spec.SHARDING_FORK_EPOCH) + 1`
|
||||
and fork at `compute_epoch_at_slot(spec.SHARDING_FORK_EPOCH)`.
|
||||
Transition to slot `compute_epoch_at_slot(spec.config.SHARDING_FORK_EPOCH) + 1`
|
||||
and fork at `compute_epoch_at_slot(spec.config.SHARDING_FORK_EPOCH)`.
|
||||
"""
|
||||
transition_to(spec, state, spec.compute_epoch_at_slot(spec.SHARDING_FORK_EPOCH))
|
||||
transition_to(spec, state, spec.compute_epoch_at_slot(spec.config.SHARDING_FORK_EPOCH))
|
||||
next_slot(spec, state)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import NewType
|
||||
|
||||
SpecForkName = NewType("SpecForkName", str)
|
||||
ConfigName = NewType("ConfigName", str)
|
||||
PresetBaseName = NewType("PresetBaseName", str)
|
||||
|
||||
@@ -32,7 +32,7 @@ def test_success(spec, state):
|
||||
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_success_multi_proposer_index_iterations(spec, state):
|
||||
next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import random
|
||||
from random import Random
|
||||
|
||||
from eth2spec.test.context import (
|
||||
spec_state_test, expect_assertion_error, always_bls, with_all_phases,
|
||||
@@ -127,7 +127,7 @@ def test_success_already_exited_recent(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_success_low_balances(spec, state):
|
||||
@@ -137,7 +137,7 @@ def test_success_low_balances(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_success_misc_balances(spec, state):
|
||||
@@ -147,14 +147,15 @@ def test_success_misc_balances(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_success_with_effective_balance_disparity(spec, state):
|
||||
# Jitter balances to be different from effective balances
|
||||
rng = Random(12345)
|
||||
for i in range(len(state.balances)):
|
||||
pre = int(state.balances[i])
|
||||
state.balances[i] += random.randrange(max(pre - 5000, 0), pre + 5000)
|
||||
state.balances[i] += rng.randrange(max(pre - 5000, 0), pre + 5000)
|
||||
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True)
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def run_voluntary_exit_processing(spec, state, signed_voluntary_exit, valid=True
|
||||
@spec_state_test
|
||||
def test_success(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -54,7 +54,7 @@ def test_success(spec, state):
|
||||
@always_bls
|
||||
def test_invalid_signature(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -72,7 +72,7 @@ def test_invalid_signature(spec, state):
|
||||
@spec_state_test
|
||||
def test_success_exit_queue(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
|
||||
@@ -116,7 +116,7 @@ def test_success_exit_queue(spec, state):
|
||||
@spec_state_test
|
||||
def test_default_exit_epoch_subsequent_exit(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -138,7 +138,7 @@ def test_default_exit_epoch_subsequent_exit(spec, state):
|
||||
@spec_state_test
|
||||
def test_validator_exit_in_future(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -157,7 +157,7 @@ def test_validator_exit_in_future(spec, state):
|
||||
@spec_state_test
|
||||
def test_validator_invalid_validator_index(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -191,7 +191,7 @@ def test_validator_not_active(spec, state):
|
||||
@spec_state_test
|
||||
def test_validator_already_exited(spec, state):
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow validator able to exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
current_epoch = spec.get_current_epoch(state)
|
||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||
@@ -218,7 +218,7 @@ def test_validator_not_active_long_enough(spec, state):
|
||||
|
||||
assert (
|
||||
current_epoch - state.validators[validator_index].activation_epoch <
|
||||
spec.SHARD_COMMITTEE_PERIOD
|
||||
spec.config.SHARD_COMMITTEE_PERIOD
|
||||
)
|
||||
|
||||
yield from run_voluntary_exit_processing(spec, state, signed_voluntary_exit, False)
|
||||
|
||||
@@ -10,7 +10,7 @@ def test_effective_balance_hysteresis(spec, state):
|
||||
run_epoch_processing_to(spec, state, 'process_effective_balance_updates')
|
||||
# Set some edge cases for balances
|
||||
max = spec.MAX_EFFECTIVE_BALANCE
|
||||
min = spec.EJECTION_BALANCE
|
||||
min = spec.config.EJECTION_BALANCE
|
||||
inc = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
div = spec.HYSTERESIS_QUOTIENT
|
||||
hys_inc = inc // div
|
||||
|
||||
@@ -153,7 +153,7 @@ def test_ejection(spec, state):
|
||||
assert state.validators[index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
# Mock an ejection
|
||||
state.validators[index].effective_balance = spec.EJECTION_BALANCE
|
||||
state.validators[index].effective_balance = spec.config.EJECTION_BALANCE
|
||||
|
||||
yield from run_process_registry_updates(spec, state)
|
||||
|
||||
@@ -174,7 +174,7 @@ def test_ejection_past_churn_limit(spec, state):
|
||||
mock_ejections = churn_limit * 3
|
||||
|
||||
for i in range(mock_ejections):
|
||||
state.validators[i].effective_balance = spec.EJECTION_BALANCE
|
||||
state.validators[i].effective_balance = spec.config.EJECTION_BALANCE
|
||||
|
||||
expected_ejection_epoch = spec.compute_activation_exit_epoch(spec.get_current_epoch(state))
|
||||
|
||||
@@ -211,7 +211,7 @@ def test_activation_queue_activation_and_ejection(spec, state):
|
||||
|
||||
# ready for ejection
|
||||
ejection_index = 2
|
||||
state.validators[ejection_index].effective_balance = spec.EJECTION_BALANCE
|
||||
state.validators[ejection_index].effective_balance = spec.config.EJECTION_BALANCE
|
||||
|
||||
yield from run_process_registry_updates(spec, state)
|
||||
|
||||
|
||||
@@ -423,7 +423,7 @@ def test_attestations_some_slashed(spec, state):
|
||||
attesting_indices_before_slashings = list(spec.get_unslashed_attesting_indices(state, attestations))
|
||||
|
||||
# Slash maximum amount of validators allowed per epoch.
|
||||
for i in range(spec.MIN_PER_EPOCH_CHURN_LIMIT):
|
||||
for i in range(spec.config.MIN_PER_EPOCH_CHURN_LIMIT):
|
||||
spec.slash_validator(state, attesting_indices_before_slashings[i])
|
||||
|
||||
if not is_post_altair(spec):
|
||||
@@ -435,5 +435,5 @@ def test_attestations_some_slashed(spec, state):
|
||||
|
||||
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
|
||||
assert len(attesting_indices) > 0
|
||||
assert len(attesting_indices_before_slashings) - len(attesting_indices) == spec.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
assert len(attesting_indices_before_slashings) - len(attesting_indices) == spec.config.MIN_PER_EPOCH_CHURN_LIMIT
|
||||
validate_resulting_balances(spec, pre_state, state, attestations)
|
||||
|
||||
@@ -82,7 +82,7 @@ def test_minimal_penalty(spec, state):
|
||||
#
|
||||
|
||||
# Just the bare minimum for this one validator
|
||||
state.balances[0] = state.validators[0].effective_balance = spec.EJECTION_BALANCE
|
||||
state.balances[0] = state.validators[0].effective_balance = spec.config.EJECTION_BALANCE
|
||||
# All the other validators get the maximum.
|
||||
for i in range(1, len(state.validators)):
|
||||
state.validators[i].effective_balance = state.balances[i] = spec.MAX_EFFECTIVE_BALANCE
|
||||
@@ -120,7 +120,7 @@ def test_scaled_penalties(spec, state):
|
||||
next_epoch(spec, state)
|
||||
|
||||
# Also mock some previous slashings, so that we test to have the delta in the penalties computation.
|
||||
base = spec.EJECTION_BALANCE
|
||||
base = spec.config.EJECTION_BALANCE
|
||||
incr = spec.EFFECTIVE_BALANCE_INCREMENT
|
||||
# Just add some random slashings. non-zero slashings are at least the minimal effective balance.
|
||||
state.slashings[0] = base + (incr * 12)
|
||||
|
||||
@@ -4,7 +4,7 @@ from eth2spec.test.context import (
|
||||
is_post_altair,
|
||||
spec_state_test,
|
||||
with_all_phases,
|
||||
with_configs,
|
||||
with_presets,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import get_valid_attestation, next_epoch_with_attestations
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
@@ -174,7 +174,7 @@ def test_shorter_chain_but_heavier_weight(spec, state):
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_filtered_block_tree(spec, state):
|
||||
test_steps = []
|
||||
# Initialization
|
||||
@@ -197,7 +197,7 @@ def test_filtered_block_tree(spec, state):
|
||||
assert state.current_justified_checkpoint.epoch > prev_state.current_justified_checkpoint.epoch
|
||||
|
||||
# tick time forward and add blocks and attestations to store
|
||||
current_time = state.slot * spec.SECONDS_PER_SLOT + store.genesis_time
|
||||
current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
for signed_block in signed_blocks:
|
||||
yield from run_on_block(spec, store, signed_block, test_steps)
|
||||
@@ -243,7 +243,7 @@ def test_filtered_block_tree(spec, state):
|
||||
attestations.append(attestation)
|
||||
|
||||
# tick time forward to be able to include up to the latest attestation
|
||||
current_time = (attestations[-1].data.slot + 1) * spec.SECONDS_PER_SLOT + store.genesis_time
|
||||
current_time = (attestations[-1].data.slot + 1) * spec.config.SECONDS_PER_SLOT + store.genesis_time
|
||||
on_tick_and_append_step(spec, store, current_time, test_steps)
|
||||
|
||||
# include rogue block and associated attestations in the store
|
||||
|
||||
@@ -2,7 +2,7 @@ from eth2spec.test.context import (
|
||||
is_post_altair,
|
||||
single_phase,
|
||||
spec_test,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_all_phases,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
@@ -26,12 +26,12 @@ def eth1_init_data(eth1_block_hash, eth1_timestamp):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_initialize_beacon_state_from_eth1(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
deposits, deposit_root, _ = prepare_full_genesis_deposits(
|
||||
spec,
|
||||
spec.MAX_EFFECTIVE_BALANCE,
|
||||
@@ -40,7 +40,7 @@ def test_initialize_beacon_state_from_eth1(spec):
|
||||
)
|
||||
|
||||
eth1_block_hash = b'\x12' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
|
||||
yield from eth1_init_data(eth1_block_hash, eth1_timestamp)
|
||||
yield 'deposits', deposits
|
||||
@@ -48,7 +48,7 @@ def test_initialize_beacon_state_from_eth1(spec):
|
||||
# initialize beacon_state
|
||||
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
|
||||
|
||||
assert state.genesis_time == eth1_timestamp + spec.GENESIS_DELAY
|
||||
assert state.genesis_time == eth1_timestamp + spec.config.GENESIS_DELAY
|
||||
assert len(state.validators) == deposit_count
|
||||
assert state.eth1_data.deposit_root == deposit_root
|
||||
assert state.eth1_data.deposit_count == deposit_count
|
||||
@@ -62,12 +62,12 @@ def test_initialize_beacon_state_from_eth1(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_initialize_beacon_state_some_small_balances(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
main_deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
|
||||
spec, spec.MAX_EFFECTIVE_BALANCE,
|
||||
deposit_count=main_deposit_count, signed=True,
|
||||
@@ -83,7 +83,7 @@ def test_initialize_beacon_state_some_small_balances(spec):
|
||||
deposits = main_deposits + small_deposits
|
||||
|
||||
eth1_block_hash = b'\x12' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
|
||||
yield from eth1_init_data(eth1_block_hash, eth1_timestamp)
|
||||
yield 'deposits', deposits
|
||||
@@ -91,7 +91,7 @@ def test_initialize_beacon_state_some_small_balances(spec):
|
||||
# initialize beacon_state
|
||||
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
|
||||
|
||||
assert state.genesis_time == eth1_timestamp + spec.GENESIS_DELAY
|
||||
assert state.genesis_time == eth1_timestamp + spec.config.GENESIS_DELAY
|
||||
assert len(state.validators) == small_deposit_count
|
||||
assert state.eth1_data.deposit_root == deposit_root
|
||||
assert state.eth1_data.deposit_count == len(deposits)
|
||||
@@ -106,13 +106,13 @@ def test_initialize_beacon_state_some_small_balances(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_initialize_beacon_state_one_topup_activation(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
# Submit all but one deposit as MAX_EFFECTIVE_BALANCE
|
||||
main_deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
|
||||
main_deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
|
||||
main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
|
||||
spec, spec.MAX_EFFECTIVE_BALANCE,
|
||||
deposit_count=main_deposit_count, signed=True,
|
||||
@@ -139,7 +139,7 @@ def test_initialize_beacon_state_one_topup_activation(spec):
|
||||
deposits = main_deposits + partial_deposits + top_up_deposits
|
||||
|
||||
eth1_block_hash = b'\x13' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
|
||||
yield from eth1_init_data(eth1_block_hash, eth1_timestamp)
|
||||
yield 'deposits', deposits
|
||||
@@ -155,7 +155,7 @@ def test_initialize_beacon_state_one_topup_activation(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_initialize_beacon_state_random_invalid_genesis(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
@@ -167,7 +167,7 @@ def test_initialize_beacon_state_random_invalid_genesis(spec):
|
||||
max_pubkey_index=10,
|
||||
)
|
||||
eth1_block_hash = b'\x14' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME + 1
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME + 1
|
||||
|
||||
yield from eth1_init_data(eth1_block_hash, eth1_timestamp)
|
||||
yield 'deposits', deposits
|
||||
@@ -182,7 +182,7 @@ def test_initialize_beacon_state_random_invalid_genesis(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_initialize_beacon_state_random_valid_genesis(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
@@ -191,22 +191,22 @@ def test_initialize_beacon_state_random_valid_genesis(spec):
|
||||
random_deposits, _, deposit_data_list = prepare_random_genesis_deposits(
|
||||
spec,
|
||||
deposit_count=20,
|
||||
min_pubkey_index=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 5,
|
||||
max_pubkey_index=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 5,
|
||||
min_pubkey_index=spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 5,
|
||||
max_pubkey_index=spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 5,
|
||||
)
|
||||
|
||||
# Then make spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT full deposits
|
||||
# Then make spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT full deposits
|
||||
full_deposits, _, _ = prepare_full_genesis_deposits(
|
||||
spec,
|
||||
spec.MAX_EFFECTIVE_BALANCE,
|
||||
deposit_count=spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT,
|
||||
deposit_count=spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT,
|
||||
signed=True,
|
||||
deposit_data_list=deposit_data_list
|
||||
)
|
||||
|
||||
deposits = random_deposits + full_deposits
|
||||
eth1_block_hash = b'\x15' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME + 2
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME + 2
|
||||
|
||||
yield from eth1_init_data(eth1_block_hash, eth1_timestamp)
|
||||
yield 'deposits', deposits
|
||||
|
||||
@@ -2,7 +2,7 @@ from eth2spec.test.context import (
|
||||
is_post_altair,
|
||||
spec_test,
|
||||
single_phase,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_all_phases,
|
||||
)
|
||||
from eth2spec.test.helpers.constants import MINIMAL
|
||||
@@ -16,7 +16,7 @@ def get_post_altair_description(spec):
|
||||
|
||||
|
||||
def create_valid_beacon_state(spec):
|
||||
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
|
||||
deposits, _, _ = prepare_full_genesis_deposits(
|
||||
spec,
|
||||
amount=spec.MAX_EFFECTIVE_BALANCE,
|
||||
@@ -25,7 +25,7 @@ def create_valid_beacon_state(spec):
|
||||
)
|
||||
|
||||
eth1_block_hash = b'\x12' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
return spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ def run_is_valid_genesis_state(spec, state, valid=True):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_is_valid_genesis_state_true(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
@@ -57,13 +57,13 @@ def test_is_valid_genesis_state_true(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_is_valid_genesis_state_false_invalid_timestamp(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
state = create_valid_beacon_state(spec)
|
||||
state.genesis_time = spec.MIN_GENESIS_TIME - 1
|
||||
state.genesis_time = spec.config.MIN_GENESIS_TIME - 1
|
||||
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=False)
|
||||
|
||||
@@ -71,7 +71,7 @@ def test_is_valid_genesis_state_false_invalid_timestamp(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_is_valid_genesis_state_true_more_balance(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
@@ -85,12 +85,12 @@ def test_is_valid_genesis_state_true_more_balance(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_is_valid_genesis_state_true_one_more_validator(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 1
|
||||
deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT + 1
|
||||
deposits, _, _ = prepare_full_genesis_deposits(
|
||||
spec,
|
||||
amount=spec.MAX_EFFECTIVE_BALANCE,
|
||||
@@ -99,7 +99,7 @@ def test_is_valid_genesis_state_true_one_more_validator(spec):
|
||||
)
|
||||
|
||||
eth1_block_hash = b'\x12' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
|
||||
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=True)
|
||||
@@ -108,12 +108,12 @@ def test_is_valid_genesis_state_true_one_more_validator(spec):
|
||||
@with_all_phases
|
||||
@spec_test
|
||||
@single_phase
|
||||
@with_configs([MINIMAL], reason="too slow")
|
||||
@with_presets([MINIMAL], reason="too slow")
|
||||
def test_is_valid_genesis_state_false_not_enough_validator(spec):
|
||||
if is_post_altair(spec):
|
||||
yield 'description', 'meta', get_post_altair_description(spec)
|
||||
|
||||
deposit_count = spec.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
|
||||
deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT - 1
|
||||
deposits, _, _ = prepare_full_genesis_deposits(
|
||||
spec,
|
||||
amount=spec.MAX_EFFECTIVE_BALANCE,
|
||||
@@ -122,7 +122,7 @@ def test_is_valid_genesis_state_false_not_enough_validator(spec):
|
||||
)
|
||||
|
||||
eth1_block_hash = b'\x12' * 32
|
||||
eth1_timestamp = spec.MIN_GENESIS_TIME
|
||||
eth1_timestamp = spec.config.MIN_GENESIS_TIME
|
||||
state = spec.initialize_beacon_state_from_eth1(eth1_block_hash, eth1_timestamp, deposits)
|
||||
|
||||
yield from run_is_valid_genesis_state(spec, state, valid=False)
|
||||
|
||||
@@ -36,7 +36,7 @@ def test_full_random_3(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_full_random_low_balances_0(spec, state):
|
||||
@@ -44,7 +44,7 @@ def test_full_random_low_balances_0(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_full_random_low_balances_1(spec, state):
|
||||
@@ -52,7 +52,7 @@ def test_full_random_low_balances_1(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=misc_balances, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@spec_test
|
||||
@single_phase
|
||||
def test_full_random_misc_balances(spec, state):
|
||||
|
||||
@@ -30,7 +30,7 @@ from eth2spec.test.context import (
|
||||
with_phases, with_all_phases, single_phase,
|
||||
expect_assertion_error, always_bls,
|
||||
disable_process_reveal_deadlines,
|
||||
with_configs,
|
||||
with_presets,
|
||||
with_custom_state,
|
||||
large_validator_set,
|
||||
is_post_altair,
|
||||
@@ -98,10 +98,10 @@ def test_empty_block_transition(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_configs([MINIMAL],
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_empty_block_transition_large_validator_set(spec, state):
|
||||
pre_slot = state.slot
|
||||
@@ -326,10 +326,10 @@ def test_empty_epoch_transition(spec, state):
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_configs([MINIMAL],
|
||||
@with_presets([MINIMAL],
|
||||
reason="mainnet config leads to larger validator set than limit of public/private keys pre-generated")
|
||||
@spec_test
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.EJECTION_BALANCE)
|
||||
@with_custom_state(balances_fn=large_validator_set, threshold_fn=lambda spec: spec.config.EJECTION_BALANCE)
|
||||
@single_phase
|
||||
def test_empty_epoch_transition_large_validator_set(spec, state):
|
||||
pre_slot = state.slot
|
||||
@@ -814,7 +814,7 @@ def test_voluntary_exit(spec, state):
|
||||
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
signed_exits = prepare_signed_exits(spec, state, [validator_index])
|
||||
yield 'pre', state
|
||||
@@ -842,7 +842,7 @@ def test_double_validator_exit_same_block(spec, state):
|
||||
validator_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1]
|
||||
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
# Same index tries to exit twice, but should only be able to do so once.
|
||||
signed_exits = prepare_signed_exits(spec, state, [validator_index, validator_index])
|
||||
@@ -866,7 +866,7 @@ def test_multiple_different_validator_exits_same_block(spec, state):
|
||||
for i in range(3)
|
||||
]
|
||||
# move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
|
||||
state.slot += spec.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
|
||||
signed_exits = prepare_signed_exits(spec, state, validator_indices)
|
||||
yield 'pre', state
|
||||
@@ -916,7 +916,7 @@ def test_balance_driven_status_transitions(spec, state):
|
||||
assert state.validators[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||
|
||||
# set validator balance to below ejection threshold
|
||||
state.validators[validator_index].effective_balance = spec.EJECTION_BALANCE
|
||||
state.validators[validator_index].effective_balance = spec.config.EJECTION_BALANCE
|
||||
|
||||
yield 'pre', state
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
||||
@spec_state_test
|
||||
def test_on_attestation_current_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * 2)
|
||||
spec.on_tick(store, store.time + spec.config.SECONDS_PER_SLOT * 2)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
@@ -54,7 +54,7 @@ def test_on_attestation_current_epoch(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_previous_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
spec.on_tick(store, store.time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
@@ -75,7 +75,7 @@ def test_on_attestation_past_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
|
||||
# move time forward 2 epochs
|
||||
time = store.time + 2 * spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
time = store.time + 2 * spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
spec.on_tick(store, time)
|
||||
|
||||
# create and store block from 3 epochs ago
|
||||
@@ -95,7 +95,7 @@ def test_on_attestation_past_epoch(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_mismatched_target_and_slot(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
spec.on_tick(store, store.time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
@@ -118,7 +118,7 @@ def test_on_attestation_mismatched_target_and_slot(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_inconsistent_target_and_head(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
spec.on_tick(store, store.time + 2 * spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
spec.on_tick(store, store.time + 2 * spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
|
||||
# Create chain 1 as empty chain between genesis and start of 1st epoch
|
||||
target_state_1 = state.copy()
|
||||
@@ -156,7 +156,7 @@ def test_on_attestation_inconsistent_target_and_head(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_target_block_not_in_store(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
spec.on_tick(store, time)
|
||||
|
||||
# move to immediately before next epoch to make block new target
|
||||
@@ -178,7 +178,7 @@ def test_on_attestation_target_block_not_in_store(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_target_checkpoint_not_in_store(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
spec.on_tick(store, time)
|
||||
|
||||
# move to immediately before next epoch to make block new target
|
||||
@@ -203,7 +203,7 @@ def test_on_attestation_target_checkpoint_not_in_store(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_target_checkpoint_not_in_store_diff_slot(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
spec.on_tick(store, time)
|
||||
|
||||
# move to two slots before next epoch to make target block one before an empty slot
|
||||
@@ -230,7 +230,7 @@ def test_on_attestation_target_checkpoint_not_in_store_diff_slot(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_beacon_block_not_in_store(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1)
|
||||
spec.on_tick(store, time)
|
||||
|
||||
# move to immediately before next epoch to make block new target
|
||||
@@ -259,7 +259,7 @@ def test_on_attestation_beacon_block_not_in_store(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_future_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + 3 * spec.SECONDS_PER_SLOT
|
||||
time = store.time + 3 * spec.config.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
@@ -279,7 +279,7 @@ def test_on_attestation_future_epoch(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_future_block(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT * 5
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT * 5
|
||||
spec.on_tick(store, time)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
@@ -299,7 +299,7 @@ def test_on_attestation_future_block(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_same_slot(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + spec.SECONDS_PER_SLOT
|
||||
time = store.time + spec.config.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
@@ -315,7 +315,7 @@ def test_on_attestation_same_slot(spec, state):
|
||||
@spec_state_test
|
||||
def test_on_attestation_invalid_attestation(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
time = store.time + 3 * spec.SECONDS_PER_SLOT
|
||||
time = store.time + 3 * spec.config.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
|
||||
@@ -30,7 +30,7 @@ def apply_next_epoch_with_attestations(spec, state, store):
|
||||
store.blocks[block_root] = block
|
||||
store.block_states[block_root] = post_state
|
||||
last_signed_block = signed_block
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
return post_state, store, last_signed_block
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ def test_basic(spec, state):
|
||||
run_on_block(spec, store, signed_block)
|
||||
|
||||
# On receiving a block of next epoch
|
||||
store.time = time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
store.time = time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
@@ -67,10 +67,10 @@ def test_on_block_checkpoints(spec, state):
|
||||
spec.on_tick(store, time)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store)
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
last_block_root = hash_tree_root(last_signed_block.message)
|
||||
|
||||
# Mock the finalized_checkpoint
|
||||
@@ -153,7 +153,7 @@ def test_on_block_finalized_skip_slots(spec, state):
|
||||
# Build block that includes the skipped slots up to finality in chain
|
||||
block = build_empty_block(spec, state, spec.compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + 2)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
run_on_block(spec, store, signed_block)
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ def test_on_block_finalized_skip_slots_not_in_skip_chain(spec, state):
|
||||
# Includes finalized block in chain, but not at appropriate skip slot
|
||||
block = build_empty_block(spec, state, spec.compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + 2)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
run_on_block(spec, store, signed_block, False)
|
||||
|
||||
|
||||
@@ -191,10 +191,10 @@ def test_on_block_update_justified_checkpoint_within_safe_slots(spec, state):
|
||||
spec.on_tick(store, time)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store)
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
last_block_root = hash_tree_root(last_signed_block.message)
|
||||
|
||||
# Mock the justified checkpoint
|
||||
@@ -222,7 +222,7 @@ def test_on_block_outside_safe_slots_and_multiple_better_justified(spec, state):
|
||||
spec.on_tick(store, time)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store)
|
||||
last_block_root = hash_tree_root(last_signed_block.message)
|
||||
|
||||
@@ -233,14 +233,14 @@ def test_on_block_outside_safe_slots_and_multiple_better_justified(spec, state):
|
||||
)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
|
||||
# Create new higher justified checkpoint not in branch of store's justified checkpoint
|
||||
just_block = build_empty_block_for_next_slot(spec, state)
|
||||
store.blocks[just_block.hash_tree_root()] = just_block
|
||||
|
||||
# Step time past safe slots
|
||||
spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.config.SECONDS_PER_SLOT)
|
||||
assert spec.get_current_slot(store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED
|
||||
|
||||
previously_justified = store.justified_checkpoint
|
||||
@@ -277,7 +277,7 @@ def test_on_block_outside_safe_slots_but_finality(spec, state):
|
||||
spec.on_tick(store, time)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store)
|
||||
last_block_root = hash_tree_root(last_signed_block.message)
|
||||
|
||||
@@ -288,14 +288,14 @@ def test_on_block_outside_safe_slots_but_finality(spec, state):
|
||||
)
|
||||
|
||||
next_epoch(spec, state)
|
||||
spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + state.slot * spec.config.SECONDS_PER_SLOT)
|
||||
|
||||
# Create new higher justified checkpoint not in branch of store's justified checkpoint
|
||||
just_block = build_empty_block_for_next_slot(spec, state)
|
||||
store.blocks[just_block.hash_tree_root()] = just_block
|
||||
|
||||
# Step time past safe slots
|
||||
spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT)
|
||||
spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.config.SECONDS_PER_SLOT)
|
||||
assert spec.get_current_slot(store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED
|
||||
|
||||
# Mock justified and finalized update in state
|
||||
|
||||
@@ -30,7 +30,7 @@ def test_update_justified_single(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
next_epoch = spec.get_current_epoch(state) + 1
|
||||
next_epoch_start_slot = spec.compute_start_slot_at_epoch(next_epoch)
|
||||
seconds_until_next_epoch = next_epoch_start_slot * spec.SECONDS_PER_SLOT - store.time
|
||||
seconds_until_next_epoch = next_epoch_start_slot * spec.config.SECONDS_PER_SLOT - store.time
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
@@ -44,7 +44,7 @@ def test_update_justified_single(spec, state):
|
||||
@spec_state_test
|
||||
def test_no_update_same_slot_at_epoch_boundary(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
seconds_per_epoch = spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
@@ -67,14 +67,14 @@ def test_no_update_not_epoch_boundary(spec, state):
|
||||
root=b'\x55' * 32,
|
||||
)
|
||||
|
||||
run_on_tick(spec, store, store.time + spec.SECONDS_PER_SLOT)
|
||||
run_on_tick(spec, store, store.time + spec.config.SECONDS_PER_SLOT)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_equal_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
seconds_per_epoch = spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
@@ -93,7 +93,7 @@ def test_no_update_new_justified_equal_epoch(spec, state):
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_later_epoch(spec, state):
|
||||
store = get_genesis_forkchoice_store(spec, state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
seconds_per_epoch = spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
|
||||
@@ -41,8 +41,8 @@ def run_is_candidate_block(spec, eth1_block, period_start, success=True):
|
||||
|
||||
def get_min_new_period_epochs(spec):
|
||||
return (
|
||||
(spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2) # to seconds
|
||||
// spec.SECONDS_PER_SLOT // spec.SLOTS_PER_EPOCH
|
||||
(spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE * 2) # to seconds
|
||||
// spec.config.SECONDS_PER_SLOT // spec.SLOTS_PER_EPOCH
|
||||
)
|
||||
|
||||
|
||||
@@ -140,28 +140,29 @@ def test_get_epoch_signature(spec, state):
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_is_candidate_block(spec, state):
|
||||
period_start = spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 + 1000
|
||||
distance_duration = spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE
|
||||
period_start = distance_duration * 2 + 1000
|
||||
run_is_candidate_block(
|
||||
spec,
|
||||
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE),
|
||||
spec.Eth1Block(timestamp=period_start - distance_duration),
|
||||
period_start,
|
||||
success=True,
|
||||
)
|
||||
run_is_candidate_block(
|
||||
spec,
|
||||
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE + 1),
|
||||
spec.Eth1Block(timestamp=period_start - distance_duration + 1),
|
||||
period_start,
|
||||
success=False,
|
||||
)
|
||||
run_is_candidate_block(
|
||||
spec,
|
||||
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2),
|
||||
spec.Eth1Block(timestamp=period_start - distance_duration * 2),
|
||||
period_start,
|
||||
success=True,
|
||||
)
|
||||
run_is_candidate_block(
|
||||
spec,
|
||||
spec.Eth1Block(timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE * 2 - 1),
|
||||
spec.Eth1Block(timestamp=period_start - distance_duration * 2 - 1),
|
||||
period_start,
|
||||
success=False,
|
||||
)
|
||||
@@ -193,12 +194,12 @@ def test_get_eth1_vote_consensus_vote(spec, state):
|
||||
state.eth1_data_votes = ()
|
||||
|
||||
block_1 = spec.Eth1Block(
|
||||
timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE - 1,
|
||||
timestamp=period_start - spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE - 1,
|
||||
deposit_count=state.eth1_data.deposit_count,
|
||||
deposit_root=b'\x04' * 32,
|
||||
)
|
||||
block_2 = spec.Eth1Block(
|
||||
timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE,
|
||||
timestamp=period_start - spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE,
|
||||
deposit_count=state.eth1_data.deposit_count + 1,
|
||||
deposit_root=b'\x05' * 32,
|
||||
)
|
||||
@@ -229,12 +230,12 @@ def test_get_eth1_vote_tie(spec, state):
|
||||
|
||||
state.eth1_data_votes = ()
|
||||
block_1 = spec.Eth1Block(
|
||||
timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE - 1,
|
||||
timestamp=period_start - spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE - 1,
|
||||
deposit_count=state.eth1_data.deposit_count,
|
||||
deposit_root=b'\x04' * 32,
|
||||
)
|
||||
block_2 = spec.Eth1Block(
|
||||
timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE,
|
||||
timestamp=period_start - spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE,
|
||||
deposit_count=state.eth1_data.deposit_count + 1,
|
||||
deposit_root=b'\x05' * 32,
|
||||
)
|
||||
@@ -268,7 +269,7 @@ def test_get_eth1_vote_chain_in_past(spec, state):
|
||||
|
||||
state.eth1_data_votes = ()
|
||||
block_1 = spec.Eth1Block(
|
||||
timestamp=period_start - spec.SECONDS_PER_ETH1_BLOCK * spec.ETH1_FOLLOW_DISTANCE,
|
||||
timestamp=period_start - spec.config.SECONDS_PER_ETH1_BLOCK * spec.config.ETH1_FOLLOW_DISTANCE,
|
||||
deposit_count=state.eth1_data.deposit_count - 1, # Chain prior to current eth1data
|
||||
deposit_root=b'\x42' * 32,
|
||||
)
|
||||
|
||||
@@ -176,21 +176,14 @@ reveal_deadlines_setting: -- optional, can have 2 different values:
|
||||
1: `process_reveal_deadlines` is OFF.
|
||||
```
|
||||
|
||||
##### `config.yaml`
|
||||
|
||||
## Config
|
||||
The runtime-configurables may be different for specific tests.
|
||||
When present, this replaces the default runtime-config that comes with the otherwise compile-time preset settings.
|
||||
|
||||
A configuration is a separate YAML file.
|
||||
Separation of configuration and tests aims to:
|
||||
- Prevent duplication of configuration
|
||||
- Make all tests easy to upgrade (e.g. when a new config constant is introduced)
|
||||
- Clearly define which constants to use
|
||||
- Be easily shareable between clients, for cross-client short- or long-lived testnets
|
||||
- Minimize the amount of different constants permutations to compile as a client.
|
||||
*Note*: Some clients prefer compile-time constants and optimizations.
|
||||
They should compile for each configuration once, and run the corresponding tests per build target.
|
||||
- Include constants to coordinate forking with
|
||||
|
||||
The format is described in [`/configs`](../../configs/README.md#format).
|
||||
The format matches that of the `mainnet_config.yaml` and `minimal_config.yaml`,
|
||||
see the [`/configs`](../../configs/README.md#format) documentation.
|
||||
Config values that are introduced at a later fork may be omitted from tests of previous forks.
|
||||
|
||||
|
||||
## Config sourcing
|
||||
|
||||
@@ -358,10 +358,10 @@ def case05_aggregate_verify():
|
||||
def create_provider(handler_name: str,
|
||||
test_case_fn: Callable[[], Iterable[Tuple[str, Dict[str, Any]]]]) -> gen_typing.TestProvider:
|
||||
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
def prepare_fn() -> None:
|
||||
# Nothing to load / change in spec. Maybe in future forks.
|
||||
# Put the tests into the general config category, to not require any particular configuration.
|
||||
return 'general'
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
for data in test_case_fn():
|
||||
@@ -369,6 +369,7 @@ def create_provider(handler_name: str,
|
||||
(case_name, case_content) = data
|
||||
yield gen_typing.TestCase(
|
||||
fork_name=PHASE0,
|
||||
preset_name='general',
|
||||
runner_name='bls',
|
||||
handler_name=handler_name,
|
||||
suite_name='small',
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.epoch_processing.test_process_' + key for key in [
|
||||
'justification_and_finalization',
|
||||
@@ -45,4 +39,4 @@ if __name__ == "__main__":
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="epoch_processing", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="epoch_processing", all_mods=all_mods)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {'finality': 'eth2spec.test.phase0.finality.test_finality'}
|
||||
altair_mods = phase_0_mods # No additional Altair specific finality tests
|
||||
@@ -16,7 +10,7 @@ if __name__ == "__main__":
|
||||
all_mods = {
|
||||
PHASE0: phase_0_mods,
|
||||
ALTAIR: altair_mods,
|
||||
MERGE: spec_merge,
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="finality", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="finality", all_mods=all_mods)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.fork_choice.test_' + key for key in [
|
||||
'get_head',
|
||||
@@ -23,4 +17,4 @@ if __name__ == "__main__":
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="fork_choice", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="fork_choice", all_mods=all_mods)
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
from importlib import reload
|
||||
from typing import Iterable
|
||||
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MINIMAL, MAINNET
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.test.helpers.typing import SpecForkName, PresetBaseName
|
||||
from eth2spec.test.altair.fork import test_altair_fork_basic, test_altair_fork_random
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
|
||||
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests
|
||||
|
||||
|
||||
def create_provider(tests_src, config_name: str, phase: str, fork_name: str) -> gen_typing.TestProvider:
|
||||
def create_provider(tests_src, preset_name: PresetBaseName,
|
||||
phase: SpecForkName, fork_name: SpecForkName) -> gen_typing.TestProvider:
|
||||
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
config_util.prepare_config(configs_path, config_name)
|
||||
reload(spec_phase0)
|
||||
reload(spec_altair)
|
||||
return config_name
|
||||
def prepare_fn() -> None:
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
return generate_from_tests(
|
||||
@@ -25,6 +19,7 @@ def create_provider(tests_src, config_name: str, phase: str, fork_name: str) ->
|
||||
handler_name='fork',
|
||||
src=tests_src,
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
phase=phase,
|
||||
)
|
||||
|
||||
@@ -34,7 +29,7 @@ def create_provider(tests_src, config_name: str, phase: str, fork_name: str) ->
|
||||
if __name__ == "__main__":
|
||||
gen_runner.run_generator("forks", [
|
||||
create_provider(test_altair_fork_basic, MINIMAL, PHASE0, ALTAIR),
|
||||
create_provider(test_altair_fork_random, MINIMAL, PHASE0, ALTAIR),
|
||||
create_provider(test_altair_fork_basic, MAINNET, PHASE0, ALTAIR),
|
||||
create_provider(test_altair_fork_random, MINIMAL, PHASE0, ALTAIR),
|
||||
create_provider(test_altair_fork_random, MAINNET, PHASE0, ALTAIR),
|
||||
])
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.genesis.test_' + key for key in [
|
||||
'initialization',
|
||||
@@ -18,4 +13,4 @@ if __name__ == "__main__":
|
||||
ALTAIR: altair_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="genesis", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="genesis", all_mods=all_mods)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.block_processing.test_process_' + key for key in [
|
||||
'attestation',
|
||||
@@ -46,4 +40,4 @@ if __name__ == "__main__":
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="operations", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="operations", all_mods=all_mods)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.rewards.test_' + key for key in [
|
||||
'basic',
|
||||
@@ -28,4 +22,4 @@ if __name__ == "__main__":
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="rewards", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="rewards", all_mods=all_mods)
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, MERGE
|
||||
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import run_state_test_generators
|
||||
|
||||
|
||||
specs = (spec_phase0, spec_altair, spec_merge)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
phase_0_mods = {key: 'eth2spec.test.phase0.sanity.test_' + key for key in [
|
||||
'blocks',
|
||||
@@ -29,4 +22,4 @@ if __name__ == "__main__":
|
||||
MERGE: merge_mods,
|
||||
}
|
||||
|
||||
run_state_test_generators(runner_name="sanity", specs=specs, all_mods=all_mods)
|
||||
run_state_test_generators(runner_name="sanity", all_mods=all_mods)
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
from eth_utils import to_tuple
|
||||
from typing import Iterable
|
||||
from importlib import reload
|
||||
|
||||
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
||||
from eth2spec.test.helpers.typing import PresetBaseName
|
||||
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.phase0 import spec as spec
|
||||
from eth2spec.test.helpers.constants import PHASE0
|
||||
from eth2spec.phase0 import mainnet as spec_mainnet, minimal as spec_minimal
|
||||
from eth2spec.test.helpers.constants import PHASE0, MINIMAL, MAINNET
|
||||
|
||||
|
||||
def shuffling_case_fn(seed, count):
|
||||
def shuffling_case_fn(spec, seed, count):
|
||||
yield 'mapping', 'data', {
|
||||
'seed': '0x' + seed.hex(),
|
||||
'count': count,
|
||||
@@ -17,28 +16,33 @@ def shuffling_case_fn(seed, count):
|
||||
}
|
||||
|
||||
|
||||
def shuffling_case(seed, count):
|
||||
return f'shuffle_0x{seed.hex()}_{count}', lambda: shuffling_case_fn(seed, count)
|
||||
def shuffling_case(spec, seed, count):
|
||||
return f'shuffle_0x{seed.hex()}_{count}', lambda: shuffling_case_fn(spec, seed, count)
|
||||
|
||||
|
||||
@to_tuple
|
||||
def shuffling_test_cases():
|
||||
def shuffling_test_cases(spec):
|
||||
for seed in [spec.hash(seed_init_value.to_bytes(length=4, byteorder='little')) for seed_init_value in range(30)]:
|
||||
for count in [0, 1, 2, 3, 5, 10, 33, 100, 1000, 9999]:
|
||||
yield shuffling_case(seed, count)
|
||||
yield shuffling_case(spec, seed, count)
|
||||
|
||||
|
||||
def create_provider(config_name: str) -> gen_typing.TestProvider:
|
||||
def create_provider(preset_name: PresetBaseName) -> gen_typing.TestProvider:
|
||||
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
config_util.prepare_config(configs_path, config_name)
|
||||
reload(spec)
|
||||
return config_name
|
||||
def prepare_fn() -> None:
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
for (case_name, case_fn) in shuffling_test_cases():
|
||||
if preset_name == MAINNET:
|
||||
spec = spec_mainnet
|
||||
elif preset_name == MINIMAL:
|
||||
spec = spec_minimal
|
||||
else:
|
||||
raise Exception(f"unrecognized preset: {preset_name}")
|
||||
for (case_name, case_fn) in shuffling_test_cases(spec):
|
||||
yield gen_typing.TestCase(
|
||||
fork_name=PHASE0,
|
||||
preset_name=preset_name,
|
||||
runner_name='shuffling',
|
||||
handler_name='core',
|
||||
suite_name='shuffle',
|
||||
@@ -50,4 +54,4 @@ def create_provider(config_name: str) -> gen_typing.TestProvider:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
gen_runner.run_generator("shuffling", [create_provider("minimal"), create_provider("mainnet")])
|
||||
gen_runner.run_generator("shuffling", [create_provider(MINIMAL), create_provider(MAINNET)])
|
||||
|
||||
@@ -11,13 +11,14 @@ from eth2spec.test.helpers.constants import PHASE0
|
||||
|
||||
def create_provider(handler_name: str, suite_name: str, case_maker) -> gen_typing.TestProvider:
|
||||
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
return "general"
|
||||
def prepare_fn() -> None:
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
for (case_name, case_fn) in case_maker():
|
||||
yield gen_typing.TestCase(
|
||||
fork_name=PHASE0,
|
||||
preset_name="general",
|
||||
runner_name='ssz_generic',
|
||||
handler_name=handler_name,
|
||||
suite_name=suite_name,
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
from random import Random
|
||||
from typing import Iterable
|
||||
from importlib import reload
|
||||
from inspect import getmembers, isclass
|
||||
|
||||
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
||||
|
||||
from eth2spec.debug import random_value, encode
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
from eth2spec.merge import spec as spec_merge
|
||||
from eth2spec.test.helpers.constants import ALTAIR, MERGE, TESTGEN_FORKS, MINIMAL, MAINNET
|
||||
from eth2spec.test.helpers.constants import TESTGEN_FORKS, MINIMAL, MAINNET
|
||||
from eth2spec.test.context import spec_targets
|
||||
from eth2spec.utils.ssz.ssz_typing import Container
|
||||
from eth2spec.utils.ssz.ssz_impl import (
|
||||
hash_tree_root,
|
||||
@@ -40,7 +36,7 @@ def get_spec_ssz_types(spec):
|
||||
]
|
||||
|
||||
|
||||
def ssz_static_cases(fork_name: str, seed: int, name, ssz_type,
|
||||
def ssz_static_cases(fork_name: str, preset_name: str, seed: int, name, ssz_type,
|
||||
mode: random_value.RandomizationMode, chaos: bool, count: int):
|
||||
random_mode_name = mode.to_name()
|
||||
|
||||
@@ -50,6 +46,7 @@ def ssz_static_cases(fork_name: str, seed: int, name, ssz_type,
|
||||
for i in range(count):
|
||||
yield gen_typing.TestCase(
|
||||
fork_name=fork_name,
|
||||
preset_name=preset_name,
|
||||
runner_name='ssz_static',
|
||||
handler_name=name,
|
||||
suite_name=f"ssz_{random_mode_name}{'_chaos' if chaos else ''}",
|
||||
@@ -58,26 +55,17 @@ def ssz_static_cases(fork_name: str, seed: int, name, ssz_type,
|
||||
)
|
||||
|
||||
|
||||
def create_provider(fork_name, config_name: str, seed: int, mode: random_value.RandomizationMode, chaos: bool,
|
||||
def create_provider(fork_name, preset_name: str, seed: int, mode: random_value.RandomizationMode, chaos: bool,
|
||||
cases_if_random: int) -> gen_typing.TestProvider:
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
# Apply changes to presets, this affects some of the vector types.
|
||||
config_util.prepare_config(configs_path, config_name)
|
||||
reload(spec_phase0)
|
||||
reload(spec_altair)
|
||||
reload(spec_merge)
|
||||
return config_name
|
||||
def prepare_fn() -> None:
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
count = cases_if_random if chaos or mode.is_changing() else 1
|
||||
spec = spec_phase0
|
||||
if fork_name == ALTAIR:
|
||||
spec = spec_altair
|
||||
elif fork_name == MERGE:
|
||||
spec = spec_merge
|
||||
spec = spec_targets[preset_name][fork_name]
|
||||
|
||||
for (i, (name, ssz_type)) in enumerate(get_spec_ssz_types(spec)):
|
||||
yield from ssz_static_cases(fork_name, seed * 1000 + i, name, ssz_type, mode, chaos, count)
|
||||
yield from ssz_static_cases(fork_name, preset_name, seed * 1000 + i, name, ssz_type, mode, chaos, count)
|
||||
|
||||
return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn)
|
||||
|
||||
@@ -95,6 +83,6 @@ if __name__ == "__main__":
|
||||
seed += 1
|
||||
for fork in TESTGEN_FORKS:
|
||||
gen_runner.run_generator("ssz_static", [
|
||||
create_provider(fork, config_name, seed, mode, chaos, cases_if_random)
|
||||
for (seed, config_name, mode, chaos, cases_if_random) in settings
|
||||
create_provider(fork, preset_name, seed, mode, chaos, cases_if_random)
|
||||
for (seed, preset_name, mode, chaos, cases_if_random) in settings
|
||||
])
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
from importlib import reload
|
||||
from typing import Iterable
|
||||
|
||||
from eth2spec.test.helpers.constants import ALTAIR, MINIMAL, MAINNET, PHASE0
|
||||
from eth2spec.config import config_util
|
||||
from eth2spec.test.altair.transition import test_transition as test_altair_transition
|
||||
from eth2spec.phase0 import spec as spec_phase0
|
||||
from eth2spec.altair import spec as spec_altair
|
||||
|
||||
from eth2spec.gen_helpers.gen_base import gen_runner, gen_typing
|
||||
from eth2spec.gen_helpers.gen_from_tests.gen import generate_from_tests
|
||||
|
||||
|
||||
def create_provider(tests_src, config_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
|
||||
def create_provider(tests_src, preset_name: str, pre_fork_name: str, post_fork_name: str) -> gen_typing.TestProvider:
|
||||
|
||||
def prepare_fn(configs_path: str) -> str:
|
||||
config_util.prepare_config(configs_path, config_name)
|
||||
reload(spec_phase0)
|
||||
reload(spec_altair)
|
||||
return config_name
|
||||
def prepare_fn() -> None:
|
||||
return
|
||||
|
||||
def cases_fn() -> Iterable[gen_typing.TestCase]:
|
||||
return generate_from_tests(
|
||||
@@ -26,6 +19,7 @@ def create_provider(tests_src, config_name: str, pre_fork_name: str, post_fork_n
|
||||
src=tests_src,
|
||||
fork_name=post_fork_name,
|
||||
phase=pre_fork_name,
|
||||
preset_name=preset_name,
|
||||
)
|
||||
|
||||
return gen_typing.TestProvider(prepare=prepare_fn, make_cases=cases_fn)
|
||||
|
||||
Reference in New Issue
Block a user