diff --git a/configs/constant_presets/README.md b/configs/constant_presets/README.md new file mode 100644 index 000000000..45148862e --- /dev/null +++ b/configs/constant_presets/README.md @@ -0,0 +1,20 @@ +# Constant Presets + +This directory contains a set of constants presets used for testing, testnets, and mainnet. + +A preset file contains all the constants known for its target. +Later-fork constants can be ignored, e.g. ignore phase1 constants as a client that only supports phase 0 currently. + +## Format + +Each preset is a key-value mapping. + +**Key**: an `UPPER_SNAKE_CASE` (a.k.a. "macro case") formatted string, name of the constant. +**Value**: can be any of: + - 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.yaml` for a complete example. + diff --git a/configs/constant_presets/mainnet.yaml b/configs/constant_presets/mainnet.yaml new file mode 100644 index 000000000..6eef9ad81 --- /dev/null +++ b/configs/constant_presets/mainnet.yaml @@ -0,0 +1,124 @@ +# Mainnet preset +# Note: the intention of this file (for now) is to illustrate what a mainnet configuration could look like. +# Some of these constants may still change before the launch of Phase 0. + + +# Misc +# --------------------------------------------------------------- +# 2**10 ` (= 1,024) +SHARD_COUNT: 1024 +# 2**7 ` (= 128) +TARGET_COMMITTEE_SIZE: 128 +# 2**5 ` (= 32) +MAX_BALANCE_CHURN_QUOTIENT: 32 +# 2**12 ` (= 4,096) +MAX_ATTESTATION_PARTICIPANTS: 4096 +# 2**2 ` (= 4) +MAX_EXIT_DEQUEUES_PER_EPOCH: 4 +# See issue 563 +SHUFFLE_ROUND_COUNT: 90 + + +# Deposit contract +# --------------------------------------------------------------- +# **TBD** +DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123567890123456789012357890 +# 2**5 ` (= 32) +DEPOSIT_CONTRACT_TREE_DEPTH: 32 + + +# 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_DEPOSIT_AMOUNT: 32000000000 +# 2**4 * 10**9 ` (= 16,000,000,000) Gwei +EJECTION_BALANCE: 16000000000 +# 2**0 * 10**9 ` (= 1,000,000,000) Gwei +HIGH_BALANCE_INCREMENT: 1000000000 + + +# Initial values +# --------------------------------------------------------------- +GENESIS_FORK_VERSION: 0x00000000 +# 2**32, GENESIS_EPOCH is derived from this constant +GENESIS_SLOT: 4294967296 +GENESIS_START_SHARD: 0 +# 2**64 - 1 +FAR_FUTURE_EPOCH: 18446744073709551615 +BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 + + +# Time parameters +# --------------------------------------------------------------- +# 6 seconds 6 seconds +SECONDS_PER_SLOT: 6 +# 2**2 ` (= 4) slots 24 seconds +MIN_ATTESTATION_INCLUSION_DELAY: 4 +# 2**6 ` (= 64) slots 6.4 minutes +SLOTS_PER_EPOCH: 64 +# 2**0 ` (= 1) epochs 6.4 minutes +MIN_SEED_LOOKAHEAD: 1 +# 2**2 ` (= 4) epochs 25.6 minutes +ACTIVATION_EXIT_DELAY: 4 +# 2**4 ` (= 16) epochs ~1.7 hours +EPOCHS_PER_ETH1_VOTING_PERIOD: 16 +# 2**13 ` (= 8,192) slots ~13 hours +SLOTS_PER_HISTORICAL_ROOT: 8192 +# 2**8 ` (= 256) epochs ~27 hours +MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 +# 2**11 ` (= 2,048) epochs 9 days +PERSISTENT_COMMITTEE_PERIOD: 2048 +# 2**6 ` (= 64) +MAX_CROSSLINK_EPOCHS: 64 + + +# State list lengths +# --------------------------------------------------------------- +# 2**13 ` (= 8,192) epochs ~36 days +LATEST_RANDAO_MIXES_LENGTH: 8192 +# 2**13 ` (= 8,192) epochs ~36 days +LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 8192 +# 2**13 ` (= 8,192) epochs ~36 days +LATEST_SLASHED_EXIT_LENGTH: 8192 + + +# Reward and penalty quotients +# --------------------------------------------------------------- +# 2**5 ` (= 32) +BASE_REWARD_QUOTIENT: 32 +# 2**9 ` (= 512) +WHISTLEBLOWING_REWARD_QUOTIENT: 512 +# 2**3 ` (= 8) +PROPOSER_REWARD_QUOTIENT: 8 +# 2**24 ` (= 16,777,216) +INACTIVITY_PENALTY_QUOTIENT: 16777216 + + +# Max operations per block +# --------------------------------------------------------------- +# 2**5 ` (= 32) +MIN_PENALTY_QUOTIENT: 32 +# 2**4 ` (= 16) +MAX_PROPOSER_SLASHINGS: 16 +# 2**0 ` (= 1) +MAX_ATTESTER_SLASHINGS: 1 +# 2**7 ` (= 128) +MAX_ATTESTATIONS: 128 +# 2**4 ` (= 16) +MAX_DEPOSITS: 16 +# 2**4 ` (= 16) +MAX_VOLUNTARY_EXITS: 16 +# 2**4 ` (= 16) +MAX_TRANSFERS: 16 + + +# Signature domains +# --------------------------------------------------------------- +DOMAIN_BEACON_BLOCK: 0 +DOMAIN_RANDAO: 1 +DOMAIN_ATTESTATION: 2 +DOMAIN_DEPOSIT: 3 +DOMAIN_VOLUNTARY_EXIT: 4 +DOMAIN_TRANSFER: 5 \ No newline at end of file diff --git a/configs/constant_presets/minimal.yaml b/configs/constant_presets/minimal.yaml new file mode 100644 index 000000000..e4c869ded --- /dev/null +++ b/configs/constant_presets/minimal.yaml @@ -0,0 +1,124 @@ +# Minimal preset + + +# Misc +# --------------------------------------------------------------- + +# [customized] Just 8 shards for testing purposes +SHARD_COUNT: 8 + +# [customized] unsecure, but fast +TARGET_COMMITTEE_SIZE: 4 +# 2**5 ` (= 32) +MAX_BALANCE_CHURN_QUOTIENT: 32 +# 2**12 ` (= 4,096) +MAX_ATTESTATION_PARTICIPANTS: 4096 +# 2**2 ` (= 4) +MAX_EXIT_DEQUEUES_PER_EPOCH: 4 +# See issue 563 +SHUFFLE_ROUND_COUNT: 90 + + +# Deposit contract +# --------------------------------------------------------------- +# **TBD** +DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123567890123456789012357890 +# 2**5 ` (= 32) +DEPOSIT_CONTRACT_TREE_DEPTH: 32 + + +# 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_DEPOSIT_AMOUNT: 32000000000 +# 2**4 * 10**9 ` (= 16,000,000,000) Gwei +EJECTION_BALANCE: 16000000000 +# 2**0 * 10**9 ` (= 1,000,000,000) Gwei +HIGH_BALANCE_INCREMENT: 1000000000 + + +# Initial values +# --------------------------------------------------------------- +GENESIS_FORK_VERSION: 0x00000000 +# 2**32, GENESIS_EPOCH is derived from this constant +GENESIS_SLOT: 4294967296 +GENESIS_START_SHARD: 0 +# 2**64 - 1 +FAR_FUTURE_EPOCH: 18446744073709551615 +BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 + + +# Time parameters +# --------------------------------------------------------------- +# 6 seconds 6 seconds +SECONDS_PER_SLOT: 6 +# [customized] 2 slots +MIN_ATTESTATION_INCLUSION_DELAY: 2 +# [customized] fast epochs +SLOTS_PER_EPOCH: 8 +# 2**0 ` (= 1) epochs 6.4 minutes +MIN_SEED_LOOKAHEAD: 1 +# 2**2 ` (= 4) epochs 25.6 minutes +ACTIVATION_EXIT_DELAY: 4 +# 2**4 ` (= 16) epochs ~1.7 hours +EPOCHS_PER_ETH1_VOTING_PERIOD: 16 +# [customized] smaller state +SLOTS_PER_HISTORICAL_ROOT: 64 +# 2**8 ` (= 256) epochs ~27 hours +MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 +# 2**11 ` (= 2,048) epochs 9 days +PERSISTENT_COMMITTEE_PERIOD: 2048 +# 2**6 ` (= 64) +MAX_CROSSLINK_EPOCHS: 64 + + +# State list lengths +# --------------------------------------------------------------- +# [customized] smaller state +LATEST_RANDAO_MIXES_LENGTH: 64 +# [customized] smaller state +LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64 +# [customized] smaller state +LATEST_SLASHED_EXIT_LENGTH: 64 + + +# Reward and penalty quotients +# --------------------------------------------------------------- +# 2**5 ` (= 32) +BASE_REWARD_QUOTIENT: 32 +# 2**9 ` (= 512) +WHISTLEBLOWING_REWARD_QUOTIENT: 512 +# 2**3 ` (= 8) +PROPOSER_REWARD_QUOTIENT: 8 +# 2**24 ` (= 16,777,216) +INACTIVITY_PENALTY_QUOTIENT: 16777216 + + +# Max operations per block +# --------------------------------------------------------------- +# 2**5 ` (= 32) +MIN_PENALTY_QUOTIENT: 32 +# 2**4 ` (= 16) +MAX_PROPOSER_SLASHINGS: 16 +# 2**0 ` (= 1) +MAX_ATTESTER_SLASHINGS: 1 +# 2**7 ` (= 128) +MAX_ATTESTATIONS: 128 +# 2**4 ` (= 16) +MAX_DEPOSITS: 16 +# 2**4 ` (= 16) +MAX_VOLUNTARY_EXITS: 16 +# 2**4 ` (= 16) +MAX_TRANSFERS: 16 + + +# Signature domains +# --------------------------------------------------------------- +DOMAIN_BEACON_BLOCK: 0 +DOMAIN_RANDAO: 1 +DOMAIN_ATTESTATION: 2 +DOMAIN_DEPOSIT: 3 +DOMAIN_VOLUNTARY_EXIT: 4 +DOMAIN_TRANSFER: 5 \ No newline at end of file diff --git a/configs/fork_timelines/README.md b/configs/fork_timelines/README.md new file mode 100644 index 000000000..c93b415f5 --- /dev/null +++ b/configs/fork_timelines/README.md @@ -0,0 +1,18 @@ +# Fork timelines + +This directory contains a set of fork timelines used for testing, testnets, and mainnet. + +A timeline file contains all the forks known for its target. +Later forks can be ignored, e.g. ignore fork `phase1` as a client that only supports phase 0 currently. + +## Format + +Each preset is a key-value mapping. + +**Key**: an `lower_snake_case` (a.k.a. "python case") formatted string, name of the fork. +**Value**: an unsigned integer number, epoch number of activation of the fork + +Timelines may contain comments to describe the values. + +See `mainnet.yaml` for a complete example. + diff --git a/configs/fork_timelines/mainnet.yaml b/configs/fork_timelines/mainnet.yaml new file mode 100644 index 000000000..8d51d6582 --- /dev/null +++ b/configs/fork_timelines/mainnet.yaml @@ -0,0 +1,12 @@ +# Mainnet fork timeline + +# Equal to GENESIS_EPOCH +phase0: 67108864 + +# Example 1: +# phase0_funny_fork_name: 67116000 + +# Example 2: +# Should be equal to PHASE_1_GENESIS_EPOCH +# (placeholder in example value here) +# phase1: 67163000 diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index fc355dd0c..843896629 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -178,6 +178,10 @@ Code snippets appearing in `this style` are to be interpreted as Python code. ## Constants +Note: the default mainnet values for the constants are included here for spec-design purposes. +The different configurations for mainnet, testnets, and yaml-based testing can be found in the `configs/constant_presets/` directory. +These configurations are updated for releases, but may be out of sync during `dev` changes. + ### Misc | Name | Value | @@ -1667,6 +1671,7 @@ def lmd_ghost(store: Store, start_state: BeaconState, start_block: BeaconBlock) children = get_children(store, head) if len(children) == 0: return head + # Ties broken by favoring block with lexicographically higher root head = max(children, key=lambda x: (get_vote_count(x), hash_tree_root(x))) ``` diff --git a/specs/test-format.md b/specs/test-format.md deleted file mode 100644 index d4256ef72..000000000 --- a/specs/test-format.md +++ /dev/null @@ -1,71 +0,0 @@ -# General test format [WIP] - -This document defines the general YAML format to which all tests should conform. Testing specifications in Eth2.0 are still a work in progress. _Expect breaking changes_ - -## ToC - -* [About](#about) -* [YAML Fields](#yaml-fields) -* [Example test suite](#example-test-suite) - -## About -Ethereum 2.0 uses YAML as the format for all cross client tests. This document describes at a high level the general format to which all test files should conform. - -The particular formats of specific types of tests (test suites) are defined in separate documents. - -## YAML fields -`title` _(required)_ - -`summary` _(optional)_ - -`test_suite` _(required)_ string defining the test suite to which the test cases conform - -`fork` _(required)_ production release versioning - -`version` _(required)_ version for particular test document - -`test_cases` _(required)_ list of test cases each of which is formatted to conform to the `test_case` standard defined by `test_suite`. All test cases have optional `name` and `description` string fields. - -## Example test suite -`shuffle` is a test suite that defines test cases for the `shuffle()` helper function defined in the `beacon-chain` spec. - -Test cases that conform to the `shuffle` test suite have the following fields: - -* `input` _(required)_ the list of items passed into `shuffle()` -* `output` _(required)_ the expected list returned by `shuffle()` -* `seed` _(required)_ the seed of entropy passed into `shuffle()` - -As for all test cases, `name` and `description` are optional string fields. - -The following is a sample YAML document for the `shuffle` test suite: - -```yaml -title: Shuffling Algorithm Tests -summary: Test vectors for shuffling a list based upon a seed using `shuffle` -test_suite: shuffle -fork: tchaikovsky -version: 1.0 - -test_cases: -- input: [] - output: [] - seed: !!binary "" -- name: boring_list - description: List with a single element, 0 - input: [0] - output: [0] - seed: !!binary "" -- input: [255] - output: [255] - seed: !!binary "" -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [1, 6, 4, 1, 6, 6, 2, 2, 4, 5] - seed: !!binary "" -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [4, 7, 10, 13, 3, 1, 2, 9, 12, 6, 11, 8, 5] - seed: !!binary "" -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 65, 2, 5, 4, 2, 6, 6, 1, 1] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -``` diff --git a/specs/test_formats/README.md b/specs/test_formats/README.md new file mode 100644 index 000000000..371c489b6 --- /dev/null +++ b/specs/test_formats/README.md @@ -0,0 +1,171 @@ +# General test format + +This document defines the YAML format and structure used for ETH 2.0 testing. + +## ToC + +* [About](#about) +* [Glossary](#glossary) +* [Test format philosophy](#test-format-philosophy) +* [Test Suite](#yaml-suite) +* [Config](#config) +* [Fork-timeline](#fork-timeline) +* [Config sourcing](#config-sourcing) +* [Test structure](#test-structure) + +## About + +Ethereum 2.0 uses YAML as the format for all cross client tests. This document describes at a high level the general format to which all test files should conform. + +The particular formats of specific types of tests (test suites) are defined in separate documents. + +## Glossary + +- `generator`: a program that outputs one or more `suite` files. + - A generator should only output one `type` of test. + - A generator is free to output multiple `suite` files, optionally with different `handler`s. +- `type`: the specialization of one single `generator`. +- `suite`: a YAML file with: + - a header: describes the `suite`, and defines what the `suite` is for + - a list of test cases +- `runner`: where a generator is a *"producer"*, this is the *"consumer"**. + - A `runner` focuses on *only one* `type`, and each type has *only one* `runner`. +- `handler`: a `runner` may be too limited sometimes, you may have a `suite` with a specific focus that requires a different format. + To facilitate this, you specify a `handler`: the runner can deal with the format by using the specified handler. + Using a `handler` in a `runner` is optional. +- `case`: a test case, an entry in the `test_cases` list of a `suite`. A case can be anything in general, + but its format should be well-defined in the documentation corresponding to the `type` (and `handler`).\ + A test has the same exact configuration and fork context as the other entries in the `case` list of its `suite`. +- `forks_timeline`: a fork timeline definition, a YAML file containing a key for each fork-name, and an epoch number as value. + +## Test format philosophy + +### Config design + +After long discussion, the following types of configured constants were identified: +- Never changing: genesis data +- Changing, but reliant on old value: e.g. an epoch time may change, but if you want to do the conversion + `(genesis data, timestamp) -> epoch number` you end up needing both constants. +- Changing, but kept around during fork transition: finalization may take a while, + e.g. an executable has to deal with new deposits and old deposits at the same time. Another example may be economic constants. +- Additional, back-wards compatible: new constants are introduced for later phases +- Changing: there is a very small chance some constant may really be *replaced*. + In this off-chance, it is likely better to include it as an additional variable, + and some clients may simply stop supporting the old one, if they do not want to sync from genesis. + +Based on these types of changes, we model the config as a list of key value pairs, + that only grows with every fork (they may change in development versions of forks however, git manages this). +With this approach, configurations are backwards compatible (older clients ignore unknown variables), and easy to maintain. + +### Fork config design + +There are two types of fork-data: +1) timeline: when does a fork take place? +2) coverage: what forks are covered by a test? + +The first is neat to have as a separate form: we prevent duplication, and can run with different presets + (e.g. fork timeline for a minimal local test, for a public testnet, or for mainnet) + +The second is still somewhat ambiguous: some tests may want cover multiple forks, and can do so in different ways: +- run one test, transitioning from one to the other +- run the same test for both +- run a test for every transition from one fork to the other +- more + +There is a common factor here however: the options are exclusive, and give a clear idea on what test suites need to be ran to cover testing for a specific fork. +The way this list of forks is interpreted, is up to the test-runner: +State-transition test suites may want to just declare forks that are being covered in the test suite, + whereas shuffling test suites may want to declare a list of forks to test the shuffling algorithm for individually. + +### Test completeness + +Tests should be independent of any sync-data. If one wants to run a test, the input data should be available from the YAML. +The aim is to provide clients with a well-defined scope of work to run a particular set of test-suites. + +- Clients that are complete are expected to contribute to testing, seeking for better resources to get conformance with the spec, and other clients. +- Clients that are not complete in functionality can choose to ignore suites that use certain test-runners, or specific handlers of these test-runners. +- Clients that are on older versions can test there work based on older releases of the generated tests, and catch up with newer releases when possible. + +## Test Suite + +``` +title: -- Display name for the test suite +summary: -- Summarizes the test suite +forks_timeline: -- Used to determine the forking timeline +forks: -- Runner decides what to do: run for each fork, or run for all at once, each fork transition, etc. + - ... +config: -- Used to determine which set of constants to run (possibly compile time) with +runner: *MUST be consistent with folder structure* +handler: *MUST be consistent with folder structure* + +test_cases: + ... + +``` + +## Config + +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 +- Shareable between clients, for cross-client short or long lived testnets +- Minimize the amounts 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. + +The format is described in `configs/constant_presets`. + + +## Fork-timeline + +A fork timeline is (preferably) loaded in as a configuration object into a client, as opposed to the constants configuration: + - we do not allocate or optimize any code based on epoch numbers + - when we transition from one fork to the other, it is preferred to stay online. + - we may decide on an epoch number for a fork based on external events (e.g. Eth1 log event), + a client should be able to activate a fork dynamically. + +The format is described in `configs/fork_timelines`. + +## Config sourcing + +The constants configurations are located in: + +``` +/configs/constant_presets/.yaml +``` + +And copied by CI for testing purposes to: + +``` +/configs/constant_presets/.yaml +``` + + +The fork timelines are located in: + +``` +/configs/fork_timelines/.yaml +``` + +And copied by CI for testing purposes to: + +``` +/configs/fork_timelines/.yaml +``` + +## Test structure + +To prevent parsing of hundreds of different YAML files to test a specific test type, + or even more specific, just a handler, tests should be structured in the following nested form: + +``` +. <--- root of eth2.0 tests repository +├── bls <--- collection of handler for a specific test-runner, example runner: "bls" +│   ├── signing <--- collection of test suites for a specific handler, example handler: "signing". If no handler, use a dummy folder "main" +│   │   ├── sign_msg.yml <--- an entry list of test suites +│   │   ... <--- more suite files (optional) +│   ... <--- more handlers +... <--- more test types +```