From 6a5405cccf8bf5786b373d6deb3a24f48d00d93e Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 24 Apr 2019 14:32:16 -0700 Subject: [PATCH 01/11] Update 0_fork-choice.md --- specs/core/0_fork-choice.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 6fdb97067..ac2e5797d 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -46,9 +46,9 @@ Note: Nodes needs to have a clock that is roughly (i.e. within `SECONDS_PER_SLOT ### Beacon chain fork choice rule -The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a [validator](#dfn-validator) `v` subjectively calculates the beacon chain head as follows. +The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a [validator](0_beacon-chain.md#dfn-validator) `v` subjectively calculates the beacon chain head as follows. -* Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the [validator](#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`. +* Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the [validator](0_beacon-chain.md#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`. * Let `finalized_head` be the finalized block with the highest epoch. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.) * Let `justified_head` be the descendant of `finalized_head` with the highest epoch that has been justified for at least 1 epoch. (A block `B` is justified if there is a descendant of `B` in `store` the processing of which sets `B` as justified.) If no such descendant exists set `justified_head` to `finalized_head`. * Let `get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as: From 0606689c2ba1146f47bc0d6cb16d0508cd512ce8 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Wed, 24 Apr 2019 14:38:58 -0700 Subject: [PATCH 02/11] Update 0_deposit-contract.md --- specs/core/0_deposit-contract.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index 6652ae2c2..16695ede8 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -9,7 +9,7 @@ - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Constants](#constants) - - [Deposit contract](#time-parameters) + - [Deposit contract](#deposit-contract) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) From 768f3ed813f61516a83ed8cf5359c93037d8396c Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Wed, 24 Apr 2019 16:57:44 -0600 Subject: [PATCH 03/11] remove validator link refs from fork choice doc --- specs/core/0_fork-choice.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index ac2e5797d..b8dd2937b 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -46,9 +46,9 @@ Note: Nodes needs to have a clock that is roughly (i.e. within `SECONDS_PER_SLOT ### Beacon chain fork choice rule -The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a [validator](0_beacon-chain.md#dfn-validator) `v` subjectively calculates the beacon chain head as follows. +The beacon chain fork choice rule is a hybrid that combines justification and finality with Latest Message Driven (LMD) Greediest Heaviest Observed SubTree (GHOST). At any point in time a validator `v` subjectively calculates the beacon chain head as follows. -* Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the [validator](0_beacon-chain.md#dfn-validator) `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`. +* Abstractly define `Store` as the type of storage object for the chain data and `store` be the set of attestations and blocks that the validator `v` has observed and verified (in particular, block ancestors must be recursively verified). Attestations not yet included in any chain are still included in `store`. * Let `finalized_head` be the finalized block with the highest epoch. (A block `B` is finalized if there is a descendant of `B` in `store` the processing of which sets `B` as finalized.) * Let `justified_head` be the descendant of `finalized_head` with the highest epoch that has been justified for at least 1 epoch. (A block `B` is justified if there is a descendant of `B` in `store` the processing of which sets `B` as justified.) If no such descendant exists set `justified_head` to `finalized_head`. * Let `get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock` be the ancestor of `block` with slot number `slot`. The `get_ancestor` function can be defined recursively as: @@ -66,7 +66,7 @@ def get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock: return get_ancestor(store, store.get_parent(block), slot) ``` -* Let `get_latest_attestation(store: Store, index: ValidatorIndex) -> Attestation` be the attestation with the highest slot number in `store` from the validator with the given `index`. If several such attestations exist, use the one the [validator](#dfn-validator) `v` observed first. +* Let `get_latest_attestation(store: Store, index: ValidatorIndex) -> Attestation` be the attestation with the highest slot number in `store` from the validator with the given `index`. If several such attestations exist, use the one the validator `v` observed first. * Let `get_latest_attestation_target(store: Store, index: ValidatorIndex) -> BeaconBlock` be the target block in the attestation `get_latest_attestation(store, index)`. * Let `get_children(store: Store, block: BeaconBlock) -> List[BeaconBlock]` returns the child blocks of the given `block`. * Let `justified_head_state` be the resulting `BeaconState` object from processing the chain up to the `justified_head`. From ff59a3eb776900889d80c8f44f8d698865a1f31d Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 25 Apr 2019 14:47:44 +0800 Subject: [PATCH 04/11] Copy from ethereum/eth2.0-specs#936 --- specs/core/0_deposit-contract.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index 6652ae2c2..95ec14f21 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -9,7 +9,7 @@ - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Constants](#constants) - - [Deposit contract](#time-parameters) + - [Deposit contract](#deposit-contract) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) @@ -51,7 +51,7 @@ The private key corresponding to `withdrawal_pubkey` will be required to initiat ### `Deposit` logs -Every Ethereum 1.0 deposit, of size between `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12 signature) is not verified by the deposit contract. +Every Ethereum 1.0 deposit, of size at least `MIN_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract. ### `Eth2Genesis` log @@ -73,4 +73,4 @@ For convenience, we provide the interface to the contract here: * `__init__()`: initializes the contract * `get_deposit_root() -> bytes32`: returns the current root of the deposit tree -* `deposit(bytes[512])`: adds a deposit instance to the deposit tree, incorporating the input argument and the value transferred in the given call. Note: the amount of value transferred *must* be within `MIN_DEPOSIT_AMOUNT` and `MAX_DEPOSIT_AMOUNT`, inclusive. Each of these constants are specified in units of Gwei. +* `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])`: adds a deposit instance to the deposit tree, incorporating the input arguments and the value transferred in the given call. Note: the amount of value transferred *must* be at least `MIN_DEPOSIT_AMOUNT`. Each of these constants are specified in units of Gwei. From c769eebff7fd47b0fda5886f878366bb61758ad6 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 25 Apr 2019 15:02:14 +0800 Subject: [PATCH 05/11] Modify the description --- specs/core/0_deposit-contract.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index 95ec14f21..a144de84b 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -9,10 +9,12 @@ - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Constants](#constants) + - [Gwei values](#gwei-values) - [Deposit contract](#deposit-contract) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - [Deposit arguments](#deposit-arguments) - [Withdrawal credentials](#withdrawal-credentials) + - [Amount](#amount) - [`Deposit` logs](#deposit-logs) - [`Eth2Genesis` log](#eth2genesis-log) - [Vyper code](#vyper-code) @@ -25,12 +27,19 @@ This document represents is the specification for the beacon chain deposit contr ## Constants +### Gwei values + +| Name | Value | Unit | +| - | - | - | +| `FULL_DEPOSIT_AMOUNT` | `32 * 10**9` | Gwei | + ### Deposit contract | Name | Value | | - | - | | `DEPOSIT_CONTRACT_ADDRESS` | **TBD** | | `DEPOSIT_CONTRACT_TREE_DEPTH` | `2**5` (= 32) | +| `CHAIN_START_FULL_DEPOSIT_THRESHOLD` | `2**16` (=65,536) | ## Ethereum 1.0 deposit contract @@ -38,7 +47,7 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus ### Deposit arguments -The deposit contract has a single `deposit` function which takes as argument a SimpleSerialize'd `DepositData`. +The deposit contract has a `deposit` function which takes the amount in Ethereum 1.0 transation, and arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to `DepositData`. ### Withdrawal credentials @@ -49,13 +58,18 @@ One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment The private key corresponding to `withdrawal_pubkey` will be required to initiate a withdrawal. It can be stored separately until a withdrawal is required, e.g. in cold storage. +### Amount + +* A valid deposit amount should be at least `MIN_DEPOSIT_AMOUNT` in Gwei. +* A deposit with an amount greater than or equal to `FULL_DEPOSIT_AMOUNT` in Gwei is considered as a full deposit. + ### `Deposit` logs Every Ethereum 1.0 deposit, of size at least `MIN_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract. ### `Eth2Genesis` log -When a sufficient amount of full deposits have been made, the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_genesis_beacon_state` function (defined below) where: +When `CHAIN_START_FULL_DEPOSIT_THRESHOLD` of full deposits have been made, the deposit contract emits the `Eth2Genesis` log. The beacon chain state may then be initialized by calling the `get_genesis_beacon_state` function (defined below) where: * `genesis_time` equals `time` in the `Eth2Genesis` log * `latest_eth1_data.deposit_root` equals `deposit_root` in the `Eth2Genesis` log From 343454fe190fbc61d1f9bd2682c5d5bd852975ce Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Thu, 25 Apr 2019 15:06:21 +0800 Subject: [PATCH 06/11] Adjust headers --- specs/core/0_deposit-contract.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index a144de84b..2c933543c 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -10,14 +10,15 @@ - [Introduction](#introduction) - [Constants](#constants) - [Gwei values](#gwei-values) - - [Deposit contract](#deposit-contract) + - [Contract](#contract) - [Ethereum 1.0 deposit contract](#ethereum-10-deposit-contract) - - [Deposit arguments](#deposit-arguments) - - [Withdrawal credentials](#withdrawal-credentials) - - [Amount](#amount) + - [Arguments](#arguments) + - [Withdrawal credentials](#withdrawal-credentials) + - [Amount](#amount) + - [Event logs](#event-logs) - [`Deposit` logs](#deposit-logs) - [`Eth2Genesis` log](#eth2genesis-log) - - [Vyper code](#vyper-code) + - [Vyper code](#vyper-code) @@ -33,7 +34,7 @@ This document represents is the specification for the beacon chain deposit contr | - | - | - | | `FULL_DEPOSIT_AMOUNT` | `32 * 10**9` | Gwei | -### Deposit contract +### Contract | Name | Value | | - | - | @@ -45,11 +46,11 @@ This document represents is the specification for the beacon chain deposit contr The initial deployment phases of Ethereum 2.0 are implemented without consensus changes to Ethereum 1.0. A deposit contract at address `DEPOSIT_CONTRACT_ADDRESS` is added to Ethereum 1.0 for deposits of ETH to the beacon chain. Validator balances will be withdrawable to the shards in phase 2, i.e. when the EVM2.0 is deployed and the shards have state. -### Deposit arguments +### Arguments The deposit contract has a `deposit` function which takes the amount in Ethereum 1.0 transation, and arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to `DepositData`. -### Withdrawal credentials +#### Withdrawal credentials One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment to credentials for withdrawals to shards. The first byte of `withdrawal_credentials` is a version number. As of now the only expected format is as follows: @@ -58,11 +59,13 @@ One of the `DepositData` fields is `withdrawal_credentials`. It is a commitment The private key corresponding to `withdrawal_pubkey` will be required to initiate a withdrawal. It can be stored separately until a withdrawal is required, e.g. in cold storage. -### Amount +#### Amount * A valid deposit amount should be at least `MIN_DEPOSIT_AMOUNT` in Gwei. * A deposit with an amount greater than or equal to `FULL_DEPOSIT_AMOUNT` in Gwei is considered as a full deposit. +## Event logs + ### `Deposit` logs Every Ethereum 1.0 deposit, of size at least `MIN_DEPOSIT_AMOUNT`, emits a `Deposit` log for consumption by the beacon chain. The deposit contract does little validation, pushing most of the validator onboarding logic to the beacon chain. In particular, the proof of possession (a BLS12-381 signature) is not verified by the deposit contract. @@ -77,7 +80,7 @@ When `CHAIN_START_FULL_DEPOSIT_THRESHOLD` of full deposits have been made, the d * `latest_eth1_data.block_hash` equals the hash of the block that included the log * `genesis_validator_deposits` is a list of `Deposit` objects built according to the `Deposit` logs up to the deposit that triggered the `Eth2Genesis` log, processed in the order in which they were emitted (oldest to newest) -### Vyper code +## Vyper code The source for the Vyper contract lives in a [separate repository](https://github.com/ethereum/deposit_contract) at [https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py](https://github.com/ethereum/deposit_contract/blob/master/deposit_contract/contracts/validator_registration.v.py). From 649dbfdf6c3a088ea0c8e444c7e8e18fd6e8357a Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 26 Apr 2019 14:43:05 +0800 Subject: [PATCH 07/11] bugfix: missing validator --- specs/core/0_beacon-chain.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 55791e25f..f7d4f8288 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1562,6 +1562,7 @@ def process_registry_updates(state: BeaconState) -> None: ], key=lambda index: state.validator_registry[index].activation_eligibility_epoch) # Dequeued validators for activation up to churn limit (without resetting activation epoch) for index in activation_queue[:get_churn_limit(state)]: + validator = state.validator_registry[index] if validator.activation_epoch == FAR_FUTURE_EPOCH: validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state)) ``` From 0de772fc1c27ea9a0d2c37ae55bf08faab4a1226 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 26 Apr 2019 14:43:21 +0800 Subject: [PATCH 08/11] Add tests/epoch_processing/test_process_registry_updates.py --- .../test_process_registry_updates.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py new file mode 100644 index 000000000..9bc70335b --- /dev/null +++ b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py @@ -0,0 +1,35 @@ +from copy import deepcopy + +import eth2spec.phase0.spec as spec + +from eth2spec.phase0.spec import ( + get_current_epoch, + is_active_validator, +) +from tests.helpers import ( + next_epoch, +) + + +def test_activation(state): + # Mock a new deposit + index = 0 + state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH + state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH + state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE + + assert not is_active_validator(state.validator_registry[index], get_current_epoch(state)) + + pre_state = deepcopy(state) + + for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): + next_epoch(state) + + assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH + assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH + assert is_active_validator( + state.validator_registry[index], + get_current_epoch(state), + ) + + return pre_state, state From 70cd3d2253e3ae40b10f62d5824e4b025eae92fd Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 26 Apr 2019 14:53:58 +0800 Subject: [PATCH 09/11] Add `test_ejection` --- .../test_process_registry_updates.py | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py index 9bc70335b..6a3f156c4 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py @@ -12,12 +12,13 @@ from tests.helpers import ( def test_activation(state): - # Mock a new deposit index = 0 + assert is_active_validator(state.validator_registry[index], get_current_epoch(state)) + + # Mock a new deposit state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE - assert not is_active_validator(state.validator_registry[index], get_current_epoch(state)) pre_state = deepcopy(state) @@ -33,3 +34,25 @@ def test_activation(state): ) return pre_state, state + + +def test_ejection(state): + index = 0 + assert is_active_validator(state.validator_registry[index], get_current_epoch(state)) + assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH + + # Mock an ejection + state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE + + pre_state = deepcopy(state) + + for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): + next_epoch(state) + + assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH + assert not is_active_validator( + state.validator_registry[index], + get_current_epoch(state), + ) + + return pre_state, state From 2e79053223554f66ceb3a39f93c3ba3c8b0fab90 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 26 Apr 2019 07:59:12 -0600 Subject: [PATCH 10/11] fix minor typo --- specs/core/0_deposit-contract.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/core/0_deposit-contract.md b/specs/core/0_deposit-contract.md index 2c933543c..6843e407e 100644 --- a/specs/core/0_deposit-contract.md +++ b/specs/core/0_deposit-contract.md @@ -48,7 +48,7 @@ The initial deployment phases of Ethereum 2.0 are implemented without consensus ### Arguments -The deposit contract has a `deposit` function which takes the amount in Ethereum 1.0 transation, and arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to `DepositData`. +The deposit contract has a `deposit` function which takes the amount in Ethereum 1.0 transaction, and arguments `pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96]` corresponding to `DepositData`. #### Withdrawal credentials From f76ade93d8a689db107b0ff05e54dce3d3a5d82f Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Fri, 26 Apr 2019 08:27:07 -0600 Subject: [PATCH 11/11] update registry tests to return the blocks that transiiton the pre_state to post_state --- specs/validator/0_beacon-chain-validator.md | 2 +- .../test_process_registry_updates.py | 17 +++++++++++++---- test_libs/pyspec/tests/helpers.py | 10 ++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index dab02b773..2d0728e7c 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -224,7 +224,7 @@ Up to `MAX_ATTESTATIONS` aggregate attestations can be included in the `block`. ##### Deposits -If there are any unprocessed deposits for the existing `state.latest_eth1_data` (i.e. `state.latest_eth1_data.deposit_count > state.deposit_index`), then pending deposits _must_ be added to the block. The expected number of deposits is exactly `min(MAX_DEPOSITS, latest_eth1_data.deposit_count - state.deposit_index)`. These [`deposits`](../core/0_beacon-chain.md#deposit) are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](../core/0_deposit-contract.md) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](../core/0_beacon-chain.md#deposits). +If there are any unprocessed deposits for the existing `state.latest_eth1_data` (i.e. `state.latest_eth1_data.deposit_count > state.deposit_index`), then pending deposits _must_ be added to the block. The expected number of deposits is exactly `min(MAX_DEPOSITS, latest_eth1_data.deposit_count - state.deposit_index)`. These [`deposits`](../core/0_beacon-chain.md#deposit) are constructed from the `Deposit` logs from the [Eth1.0 deposit contract](../core/0_deposit-contract) and must be processed in sequential order. The deposits included in the `block` must satisfy the verification conditions found in [deposits processing](../core/0_beacon-chain.md#deposits). The `proof` for each deposit must be constructed against the deposit root contained in `state.latest_eth1_data` rather than the deposit root at the time the deposit was initially logged from the 1.0 chain. This entails storing a full deposit merkle tree locally and computing updated proofs against the `latest_eth1_data.deposit_root` as needed. See [`minimal_merkle.py`](https://github.com/ethereum/research/blob/master/spec_pythonizer/utils/merkle_minimal.py) for a sample implementation. diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py index 6a3f156c4..11f5de2ad 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py @@ -1,5 +1,7 @@ from copy import deepcopy +import pytest + import eth2spec.phase0.spec as spec from eth2spec.phase0.spec import ( @@ -10,6 +12,9 @@ from tests.helpers import ( next_epoch, ) +# mark entire file as 'state' +pytestmark = pytest.mark.state + def test_activation(state): index = 0 @@ -23,8 +28,10 @@ def test_activation(state): pre_state = deepcopy(state) + blocks = [] for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): - next_epoch(state) + block = next_epoch(state) + blocks.append(block) assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH @@ -33,7 +40,7 @@ def test_activation(state): get_current_epoch(state), ) - return pre_state, state + return pre_state, blocks, state def test_ejection(state): @@ -46,8 +53,10 @@ def test_ejection(state): pre_state = deepcopy(state) + blocks = [] for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): - next_epoch(state) + block = next_epoch(state) + blocks.append(block) assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH assert not is_active_validator( @@ -55,4 +64,4 @@ def test_ejection(state): get_current_epoch(state), ) - return pre_state, state + return pre_state, blocks, state diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/helpers.py index 63e4cd710..19df560ac 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/helpers.py @@ -402,11 +402,21 @@ def add_attestation_to_state(state, attestation, slot): def next_slot(state): + """ + Transition to the next slot via an empty block. + Return the empty block that triggered the transition. + """ block = build_empty_block_for_next_slot(state) state_transition(state, block) + return block def next_epoch(state): + """ + Transition to the start slot of the next epoch via an empty block. + Return the empty block that triggered the transition. + """ block = build_empty_block_for_next_slot(state) block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) state_transition(state, block) + return block