Merge conflicts on `dev`
This commit is contained in:
commit
31a4700223
|
@ -14,3 +14,10 @@ eth2.0-spec-tests/
|
||||||
# Dynamically built from Markdown spec
|
# Dynamically built from Markdown spec
|
||||||
test_libs/pyspec/eth2spec/phase0/spec.py
|
test_libs/pyspec/eth2spec/phase0/spec.py
|
||||||
test_libs/pyspec/eth2spec/phase1/spec.py
|
test_libs/pyspec/eth2spec/phase1/spec.py
|
||||||
|
|
||||||
|
# coverage reports
|
||||||
|
.htmlcov
|
||||||
|
.coverage
|
||||||
|
|
||||||
|
# local CI testing output
|
||||||
|
test_libs/pyspec/test-reports
|
||||||
|
|
16
Makefile
16
Makefile
|
@ -21,8 +21,11 @@ PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md
|
||||||
|
|
||||||
PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS)
|
PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS)
|
||||||
|
|
||||||
|
COV_HTML_OUT=.htmlcov
|
||||||
|
COV_INDEX_FILE=$(PY_SPEC_DIR)/$(COV_HTML_OUT)/index.html
|
||||||
|
|
||||||
.PHONY: clean all test citest lint gen_yaml_tests pyspec phase0 phase1 install_test install_deposit_contract_test test_deposit_contract compile_deposit_contract
|
.PHONY: clean all test citest lint gen_yaml_tests pyspec phase0 phase1 install_test open_cov \
|
||||||
|
install_deposit_contract_test test_deposit_contract compile_deposit_contract
|
||||||
|
|
||||||
all: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_DIR) $(YAML_TEST_TARGETS)
|
all: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_DIR) $(YAML_TEST_TARGETS)
|
||||||
|
|
||||||
|
@ -32,6 +35,9 @@ clean:
|
||||||
rm -rf $(PY_SPEC_DIR)/venv $(PY_SPEC_DIR)/.pytest_cache
|
rm -rf $(PY_SPEC_DIR)/venv $(PY_SPEC_DIR)/.pytest_cache
|
||||||
rm -rf $(PY_SPEC_ALL_TARGETS)
|
rm -rf $(PY_SPEC_ALL_TARGETS)
|
||||||
rm -rf $(DEPOSIT_CONTRACT_DIR)/venv $(DEPOSIT_CONTRACT_DIR)/.pytest_cache
|
rm -rf $(DEPOSIT_CONTRACT_DIR)/venv $(DEPOSIT_CONTRACT_DIR)/.pytest_cache
|
||||||
|
rm -rf $(PY_SPEC_DIR)/$(COV_HTML_OUT)
|
||||||
|
rm -rf $(PY_SPEC_DIR)/.coverage
|
||||||
|
rm -rf $(PY_SPEC_DIR)/test-reports
|
||||||
|
|
||||||
# "make gen_yaml_tests" to run generators
|
# "make gen_yaml_tests" to run generators
|
||||||
gen_yaml_tests: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_TARGETS)
|
gen_yaml_tests: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_TARGETS)
|
||||||
|
@ -41,11 +47,15 @@ install_test:
|
||||||
cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install -r requirements-testing.txt;
|
cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install -r requirements-testing.txt;
|
||||||
|
|
||||||
test: $(PY_SPEC_ALL_TARGETS)
|
test: $(PY_SPEC_ALL_TARGETS)
|
||||||
cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest eth2spec
|
cd $(PY_SPEC_DIR); . venv/bin/activate; export PYTHONPATH="./"; \
|
||||||
|
python -m pytest --cov=eth2spec.phase0.spec --cov=eth2spec.phase1.spec --cov-report="html:$(COV_HTML_OUT)" --cov-branch eth2spec
|
||||||
|
|
||||||
citest: $(PY_SPEC_ALL_TARGETS)
|
citest: $(PY_SPEC_ALL_TARGETS)
|
||||||
cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; \
|
cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; \
|
||||||
python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml eth2spec
|
python -m pytest --junitxml=test-reports/eth2spec/test_results.xml eth2spec
|
||||||
|
|
||||||
|
open_cov:
|
||||||
|
((open "$(COV_INDEX_FILE)" || xdg-open "$(COV_INDEX_FILE)") &> /dev/null) &
|
||||||
|
|
||||||
lint: $(PY_SPEC_ALL_TARGETS)
|
lint: $(PY_SPEC_ALL_TARGETS)
|
||||||
cd $(PY_SPEC_DIR); . venv/bin/activate; \
|
cd $(PY_SPEC_DIR); . venv/bin/activate; \
|
||||||
|
|
|
@ -15,8 +15,6 @@ MAX_INDICES_PER_ATTESTATION: 4096
|
||||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||||
# 2**16 (= 65,536)
|
# 2**16 (= 65,536)
|
||||||
CHURN_LIMIT_QUOTIENT: 65536
|
CHURN_LIMIT_QUOTIENT: 65536
|
||||||
# Normalizes base rewards
|
|
||||||
BASE_REWARDS_PER_EPOCH: 5
|
|
||||||
# See issue 563
|
# See issue 563
|
||||||
SHUFFLE_ROUND_COUNT: 90
|
SHUFFLE_ROUND_COUNT: 90
|
||||||
|
|
||||||
|
@ -25,8 +23,6 @@ SHUFFLE_ROUND_COUNT: 90
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# **TBD**
|
# **TBD**
|
||||||
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
||||||
# 2**5 (= 32)
|
|
||||||
DEPOSIT_CONTRACT_TREE_DEPTH: 32
|
|
||||||
|
|
||||||
|
|
||||||
# Gwei values
|
# Gwei values
|
||||||
|
@ -46,8 +42,6 @@ EFFECTIVE_BALANCE_INCREMENT: 1000000000
|
||||||
GENESIS_FORK_VERSION: 0x00000000
|
GENESIS_FORK_VERSION: 0x00000000
|
||||||
# 0, GENESIS_EPOCH is derived from this constant
|
# 0, GENESIS_EPOCH is derived from this constant
|
||||||
GENESIS_SLOT: 0
|
GENESIS_SLOT: 0
|
||||||
# 2**64 - 1
|
|
||||||
FAR_FUTURE_EPOCH: 18446744073709551615
|
|
||||||
BLS_WITHDRAWAL_PREFIX: 0
|
BLS_WITHDRAWAL_PREFIX: 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,11 +74,11 @@ MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||||
# State list lengths
|
# State list lengths
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# 2**13 (= 8,192) epochs ~36 days
|
# 2**13 (= 8,192) epochs ~36 days
|
||||||
LATEST_RANDAO_MIXES_LENGTH: 8192
|
RANDAO_MIXES_LENGTH: 8192
|
||||||
# 2**13 (= 8,192) epochs ~36 days
|
# 2**13 (= 8,192) epochs ~36 days
|
||||||
LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 8192
|
ACTIVE_INDEX_ROOTS_LENGTH: 8192
|
||||||
# 2**13 (= 8,192) epochs ~36 days
|
# 2**13 (= 8,192) epochs ~36 days
|
||||||
LATEST_SLASHED_EXIT_LENGTH: 8192
|
SLASHED_EXIT_LENGTH: 8192
|
||||||
|
|
||||||
|
|
||||||
# Reward and penalty quotients
|
# Reward and penalty quotients
|
||||||
|
|
|
@ -14,8 +14,6 @@ MAX_INDICES_PER_ATTESTATION: 4096
|
||||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||||
# 2**16 (= 65,536)
|
# 2**16 (= 65,536)
|
||||||
CHURN_LIMIT_QUOTIENT: 65536
|
CHURN_LIMIT_QUOTIENT: 65536
|
||||||
# Normalizes base rewards
|
|
||||||
BASE_REWARDS_PER_EPOCH: 5
|
|
||||||
# [customized] Faster, but unsecure.
|
# [customized] Faster, but unsecure.
|
||||||
SHUFFLE_ROUND_COUNT: 10
|
SHUFFLE_ROUND_COUNT: 10
|
||||||
|
|
||||||
|
@ -24,8 +22,6 @@ SHUFFLE_ROUND_COUNT: 10
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# **TBD**
|
# **TBD**
|
||||||
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
||||||
# 2**5 (= 32)
|
|
||||||
DEPOSIT_CONTRACT_TREE_DEPTH: 32
|
|
||||||
|
|
||||||
|
|
||||||
# Gwei values
|
# Gwei values
|
||||||
|
@ -45,8 +41,6 @@ EFFECTIVE_BALANCE_INCREMENT: 1000000000
|
||||||
GENESIS_FORK_VERSION: 0x00000000
|
GENESIS_FORK_VERSION: 0x00000000
|
||||||
# 0, GENESIS_EPOCH is derived from this constant
|
# 0, GENESIS_EPOCH is derived from this constant
|
||||||
GENESIS_SLOT: 0
|
GENESIS_SLOT: 0
|
||||||
# 2**64 - 1
|
|
||||||
FAR_FUTURE_EPOCH: 18446744073709551615
|
|
||||||
BLS_WITHDRAWAL_PREFIX: 0
|
BLS_WITHDRAWAL_PREFIX: 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,11 +75,11 @@ EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS: 4096
|
||||||
# State list lengths
|
# State list lengths
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# [customized] smaller state
|
# [customized] smaller state
|
||||||
LATEST_RANDAO_MIXES_LENGTH: 64
|
RANDAO_MIXES_LENGTH: 64
|
||||||
# [customized] smaller state
|
# [customized] smaller state
|
||||||
LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64
|
ACTIVE_INDEX_ROOTS_LENGTH: 64
|
||||||
# [customized] smaller state
|
# [customized] smaller state
|
||||||
LATEST_SLASHED_EXIT_LENGTH: 64
|
SLASHED_EXIT_LENGTH: 64
|
||||||
|
|
||||||
|
|
||||||
# Reward and penalty quotients
|
# Reward and penalty quotients
|
||||||
|
|
|
@ -144,9 +144,10 @@ def objects_to_spec(functions: Dict[str, str],
|
||||||
"""
|
"""
|
||||||
Given all the objects that constitute a spec, combine them into a single pyfile.
|
Given all the objects that constitute a spec, combine them into a single pyfile.
|
||||||
"""
|
"""
|
||||||
new_type_definitions = \
|
new_type_definitions = '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
|
||||||
'\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
|
new_type_definitions += '\n' + '\n'.join(['Hash = Bytes32', 'BLSPubkey = Bytes48', 'BLSSignature = Bytes96'])
|
||||||
new_type_definitions += '\n' + '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
|
new_type_definitions += \
|
||||||
|
'\n' + '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
|
||||||
functions_spec = '\n\n'.join(functions.values())
|
functions_spec = '\n\n'.join(functions.values())
|
||||||
constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
|
constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
|
||||||
ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
|
ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
|
||||||
|
@ -191,7 +192,7 @@ def dependency_order_ssz_objects(objects: Dict[str, str]) -> None:
|
||||||
items = list(objects.items())
|
items = list(objects.items())
|
||||||
for key, value in items:
|
for key, value in items:
|
||||||
dependencies = re.findall(r'(: [A-Z][\w[]*)', value)
|
dependencies = re.findall(r'(: [A-Z][\w[]*)', value)
|
||||||
dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|Dict|uint\d+|Bytes\d+|bytes', '', x), dependencies)
|
dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|Hash|BLSPubkey|BLSSignature|uint\d+|Bytes\d+|bytes', '', x), dependencies)
|
||||||
for dep in dependencies:
|
for dep in dependencies:
|
||||||
if dep in NEW_TYPES or len(dep) == 0:
|
if dep in NEW_TYPES or len(dep) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,12 @@
|
||||||
- [Ethereum 2.0 Phase 0 -- Beacon Chain Fork Choice](#ethereum-20-phase-0----beacon-chain-fork-choice)
|
- [Ethereum 2.0 Phase 0 -- Beacon Chain Fork Choice](#ethereum-20-phase-0----beacon-chain-fork-choice)
|
||||||
- [Table of contents](#table-of-contents)
|
- [Table of contents](#table-of-contents)
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
|
<<<<<<< HEAD
|
||||||
- [Constants](#constants)
|
- [Constants](#constants)
|
||||||
|
=======
|
||||||
|
- [Prerequisites](#prerequisites)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
>>>>>>> dev
|
||||||
- [Time parameters](#time-parameters)
|
- [Time parameters](#time-parameters)
|
||||||
- [Fork choice](#fork-choice)
|
- [Fork choice](#fork-choice)
|
||||||
- [Containers](#containers)
|
- [Containers](#containers)
|
||||||
|
@ -30,7 +35,7 @@
|
||||||
|
|
||||||
This document is the beacon chain fork choice spec, part of Ethereum 2.0 Phase 0. It assumes the [beacon chain state transition function spec](./0_beacon-chain.md).
|
This document is the beacon chain fork choice spec, part of Ethereum 2.0 Phase 0. It assumes the [beacon chain state transition function spec](./0_beacon-chain.md).
|
||||||
|
|
||||||
## Constants
|
## Configuration
|
||||||
|
|
||||||
### Time parameters
|
### Time parameters
|
||||||
|
|
||||||
|
@ -77,7 +82,13 @@ class Store(object):
|
||||||
finalized_root: Bytes32 = ZERO_HASH
|
finalized_root: Bytes32 = ZERO_HASH
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
### Helpers
|
### Helpers
|
||||||
|
=======
|
||||||
|
* The parent block with root `block.parent_root` has been processed and accepted.
|
||||||
|
* An Ethereum 1.0 block pointed to by the `state.eth1_data.block_hash` has been processed and accepted.
|
||||||
|
* The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`.
|
||||||
|
>>>>>>> dev
|
||||||
|
|
||||||
#### `get_genesis_store`
|
#### `get_genesis_store`
|
||||||
|
|
||||||
|
|
|
@ -339,7 +339,7 @@ def process_custody_key_reveal(state: BeaconState,
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
revealer = state.validator_registry[reveal.revealer_index]
|
revealer = state.validators[reveal.revealer_index]
|
||||||
epoch_to_sign = get_randao_epoch_for_custody_period(revealer.next_custody_reveal_period, reveal.revealed_index)
|
epoch_to_sign = get_randao_epoch_for_custody_period(revealer.next_custody_reveal_period, reveal.revealed_index)
|
||||||
|
|
||||||
assert revealer.next_custody_reveal_period < get_validators_custody_reveal_period(state, reveal.revealed_index)
|
assert revealer.next_custody_reveal_period < get_validators_custody_reveal_period(state, reveal.revealed_index)
|
||||||
|
@ -389,8 +389,8 @@ def process_early_derived_secret_reveal(state: BeaconState,
|
||||||
Note that this function mutates ``state``.
|
Note that this function mutates ``state``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
revealed_validator = state.validator_registry[reveal.revealed_index]
|
revealed_validator = state.validators[reveal.revealed_index]
|
||||||
masker = state.validator_registry[reveal.masker_index]
|
masker = state.validators[reveal.masker_index]
|
||||||
derived_secret_location = reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS
|
derived_secret_location = reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS
|
||||||
|
|
||||||
assert reveal.epoch >= get_current_epoch(state) + RANDAO_PENALTY_EPOCHS
|
assert reveal.epoch >= get_current_epoch(state) + RANDAO_PENALTY_EPOCHS
|
||||||
|
@ -399,7 +399,7 @@ def process_early_derived_secret_reveal(state: BeaconState,
|
||||||
assert reveal.revealed_index not in state.exposed_derived_secrets[derived_secret_location]
|
assert reveal.revealed_index not in state.exposed_derived_secrets[derived_secret_location]
|
||||||
|
|
||||||
# Verify signature correctness
|
# Verify signature correctness
|
||||||
masker = state.validator_registry[reveal.masker_index]
|
masker = state.validators[reveal.masker_index]
|
||||||
pubkeys = [revealed_validator.pubkey, masker.pubkey]
|
pubkeys = [revealed_validator.pubkey, masker.pubkey]
|
||||||
message_hashes = [
|
message_hashes = [
|
||||||
hash_tree_root(reveal.epoch),
|
hash_tree_root(reveal.epoch),
|
||||||
|
@ -465,7 +465,7 @@ def process_chunk_challenge(state: BeaconState,
|
||||||
validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation))
|
validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation))
|
||||||
# Verify it is not too late to challenge
|
# Verify it is not too late to challenge
|
||||||
assert slot_to_epoch(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
|
assert slot_to_epoch(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
|
||||||
responder = state.validator_registry[challenge.responder_index]
|
responder = state.validators[challenge.responder_index]
|
||||||
assert responder.exit_epoch >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
|
assert responder.exit_epoch >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
|
||||||
# Verify the responder participated in the attestation
|
# Verify the responder participated in the attestation
|
||||||
attesters = get_attesting_indices(state, challenge.attestation.data, challenge.attestation.aggregation_bitfield)
|
attesters = get_attesting_indices(state, challenge.attestation.data, challenge.attestation.aggregation_bitfield)
|
||||||
|
@ -507,7 +507,7 @@ def process_bit_challenge(state: BeaconState,
|
||||||
challenge: CustodyBitChallenge) -> None:
|
challenge: CustodyBitChallenge) -> None:
|
||||||
|
|
||||||
# Verify challenge signature
|
# Verify challenge signature
|
||||||
challenger = state.validator_registry[challenge.challenger_index]
|
challenger = state.validators[challenge.challenger_index]
|
||||||
assert bls_verify(
|
assert bls_verify(
|
||||||
pubkey=challenger.pubkey,
|
pubkey=challenger.pubkey,
|
||||||
message_hash=signing_root(challenge),
|
message_hash=signing_root(challenge),
|
||||||
|
@ -520,7 +520,7 @@ def process_bit_challenge(state: BeaconState,
|
||||||
attestation = challenge.attestation
|
attestation = challenge.attestation
|
||||||
validate_indexed_attestation(state, convert_to_indexed(state, attestation))
|
validate_indexed_attestation(state, convert_to_indexed(state, attestation))
|
||||||
# Verify the attestation is eligible for challenging
|
# Verify the attestation is eligible for challenging
|
||||||
responder = state.validator_registry[challenge.responder_index]
|
responder = state.validators[challenge.responder_index]
|
||||||
assert (slot_to_epoch(attestation.data.slot) + responder.max_reveal_lateness <=
|
assert (slot_to_epoch(attestation.data.slot) + responder.max_reveal_lateness <=
|
||||||
get_validators_custody_reveal_period(state, challenge.responder_index))
|
get_validators_custody_reveal_period(state, challenge.responder_index))
|
||||||
|
|
||||||
|
@ -630,7 +630,7 @@ def process_bit_challenge_response(state: BeaconState,
|
||||||
# Verify chunk index
|
# Verify chunk index
|
||||||
assert response.chunk_index < challenge.chunk_count
|
assert response.chunk_index < challenge.chunk_count
|
||||||
# Verify responder has not been slashed
|
# Verify responder has not been slashed
|
||||||
responder = state.validator_registry[challenge.responder_index]
|
responder = state.validators[challenge.responder_index]
|
||||||
assert not responder.slashed
|
assert not responder.slashed
|
||||||
# Verify the chunk matches the crosslink data root
|
# Verify the chunk matches the crosslink data root
|
||||||
assert verify_merkle_branch(
|
assert verify_merkle_branch(
|
||||||
|
@ -669,7 +669,7 @@ Run `process_reveal_deadlines(state)` immediately after `process_registry_update
|
||||||
process_reveal_deadlines(state)
|
process_reveal_deadlines(state)
|
||||||
# end insert @process_reveal_deadlines
|
# end insert @process_reveal_deadlines
|
||||||
def process_reveal_deadlines(state: BeaconState) -> None:
|
def process_reveal_deadlines(state: BeaconState) -> None:
|
||||||
for index, validator in enumerate(state.validator_registry):
|
for index, validator in enumerate(state.validators):
|
||||||
deadline = validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD)
|
deadline = validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD)
|
||||||
if get_validators_custody_reveal_period(state, index) > deadline:
|
if get_validators_custody_reveal_period(state, index) > deadline:
|
||||||
slash_validator(state, index)
|
slash_validator(state, index)
|
||||||
|
@ -710,7 +710,7 @@ def after_process_final_updates(state: BeaconState) -> None:
|
||||||
validator_indices_in_records = set(
|
validator_indices_in_records = set(
|
||||||
[record.challenger_index for record in records] + [record.responder_index for record in records]
|
[record.challenger_index for record in records] + [record.responder_index for record in records]
|
||||||
)
|
)
|
||||||
for index, validator in enumerate(state.validator_registry):
|
for index, validator in enumerate(state.validators):
|
||||||
if index not in validator_indices_in_records:
|
if index not in validator_indices_in_records:
|
||||||
if validator.exit_epoch != FAR_FUTURE_EPOCH and validator.withdrawable_epoch == FAR_FUTURE_EPOCH:
|
if validator.exit_epoch != FAR_FUTURE_EPOCH and validator.withdrawable_epoch == FAR_FUTURE_EPOCH:
|
||||||
validator.withdrawable_epoch = validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
validator.withdrawable_epoch = validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
- [Ethereum 2.0 Phase 1 -- Shard Data Chains](#ethereum-20-phase-1----shard-data-chains)
|
- [Ethereum 2.0 Phase 1 -- Shard Data Chains](#ethereum-20-phase-1----shard-data-chains)
|
||||||
- [Table of contents](#table-of-contents)
|
- [Table of contents](#table-of-contents)
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
- [Constants](#constants)
|
- [Configuration](#configuration)
|
||||||
- [Misc](#misc)
|
- [Misc](#misc)
|
||||||
|
- [Initial values](#initial-values)
|
||||||
- [Time parameters](#time-parameters)
|
- [Time parameters](#time-parameters)
|
||||||
- [Signature domains](#signature-domains)
|
- [Signature domains](#signature-domains)
|
||||||
- [Data structures](#data-structures)
|
- [Data structures](#data-structures)
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
|
|
||||||
This document describes the shard data layer and the shard fork choice rule in Phase 1 of Ethereum 2.0.
|
This document describes the shard data layer and the shard fork choice rule in Phase 1 of Ethereum 2.0.
|
||||||
|
|
||||||
## Constants
|
## Configuration
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
|
@ -46,6 +47,10 @@ This document describes the shard data layer and the shard fork choice rule in P
|
||||||
| - | - |
|
| - | - |
|
||||||
| `BYTES_PER_SHARD_BLOCK_BODY` | `2**14` (= 16,384) |
|
| `BYTES_PER_SHARD_BLOCK_BODY` | `2**14` (= 16,384) |
|
||||||
| `MAX_SHARD_ATTESTIONS` | `2**4` (= 16) |
|
| `MAX_SHARD_ATTESTIONS` | `2**4` (= 16) |
|
||||||
|
|
||||||
|
### Initial values
|
||||||
|
|
||||||
|
| Name | Value |
|
||||||
| `PHASE_1_FORK_EPOCH` | **TBD** |
|
| `PHASE_1_FORK_EPOCH` | **TBD** |
|
||||||
| `PHASE_1_FORK_SLOT` | **TBD** |
|
| `PHASE_1_FORK_SLOT` | **TBD** |
|
||||||
| `GENESIS_SHARD_SLOT` | 0 |
|
| `GENESIS_SHARD_SLOT` | 0 |
|
||||||
|
@ -157,9 +162,9 @@ def get_persistent_committee(state: BeaconState,
|
||||||
later_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD
|
later_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD
|
||||||
|
|
||||||
committee_count = max(
|
committee_count = max(
|
||||||
len(get_active_validator_indices(state.validator_registry, earlier_start_epoch)) //
|
len(get_active_validator_indices(state.validators, earlier_start_epoch)) //
|
||||||
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
||||||
len(get_active_validator_indices(state.validator_registry, later_start_epoch)) //
|
len(get_active_validator_indices(state.validators, later_start_epoch)) //
|
||||||
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
||||||
) + 1
|
) + 1
|
||||||
|
|
||||||
|
@ -189,7 +194,7 @@ def get_shard_proposer_index(state: BeaconState,
|
||||||
|
|
||||||
# Search for an active proposer
|
# Search for an active proposer
|
||||||
for index in persistent_committee:
|
for index in persistent_committee:
|
||||||
if is_active_validator(state.validator_registry[index], get_current_epoch(state)):
|
if is_active_validator(state.validators[index], get_current_epoch(state)):
|
||||||
return index
|
return index
|
||||||
|
|
||||||
# No block can be proposed if no validator is active
|
# No block can be proposed if no validator is active
|
||||||
|
@ -223,7 +228,7 @@ def verify_shard_attestation_signature(state: BeaconState,
|
||||||
pubkeys = []
|
pubkeys = []
|
||||||
for i, index in enumerate(persistent_committee):
|
for i, index in enumerate(persistent_committee):
|
||||||
if get_bitfield_bit(attestation.aggregation_bitfield, i) == 0b1:
|
if get_bitfield_bit(attestation.aggregation_bitfield, i) == 0b1:
|
||||||
validator = state.validator_registry[index]
|
validator = state.validators[index]
|
||||||
assert is_active_validator(validator, get_current_epoch(state))
|
assert is_active_validator(validator, get_current_epoch(state))
|
||||||
pubkeys.append(validator.pubkey)
|
pubkeys.append(validator.pubkey)
|
||||||
assert bls_verify(
|
assert bls_verify(
|
||||||
|
@ -324,7 +329,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock],
|
||||||
proposer_index = get_shard_proposer_index(beacon_state, candidate.shard, candidate.slot)
|
proposer_index = get_shard_proposer_index(beacon_state, candidate.shard, candidate.slot)
|
||||||
assert proposer_index is not None
|
assert proposer_index is not None
|
||||||
assert bls_verify(
|
assert bls_verify(
|
||||||
pubkey=beacon_state.validator_registry[proposer_index].pubkey,
|
pubkey=beacon_state.validators[proposer_index].pubkey,
|
||||||
message_hash=signing_root(block),
|
message_hash=signing_root(block),
|
||||||
signature=candidate.signature,
|
signature=candidate.signature,
|
||||||
domain=get_domain(beacon_state, slot_to_epoch(candidate.slot), DOMAIN_SHARD_PROPOSER),
|
domain=get_domain(beacon_state, slot_to_epoch(candidate.slot), DOMAIN_SHARD_PROPOSER),
|
||||||
|
@ -394,7 +399,7 @@ def is_valid_beacon_attestation(shard: Shard,
|
||||||
assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot)
|
assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot)
|
||||||
|
|
||||||
# Check crosslink data root
|
# Check crosslink data root
|
||||||
start_epoch = beacon_state.latest_crosslinks[shard].epoch
|
start_epoch = beacon_state.crosslinks[shard].epoch
|
||||||
end_epoch = min(slot_to_epoch(candidate.data.slot) - CROSSLINK_LOOKBACK, start_epoch + MAX_EPOCHS_PER_CROSSLINK)
|
end_epoch = min(slot_to_epoch(candidate.data.slot) - CROSSLINK_LOOKBACK, start_epoch + MAX_EPOCHS_PER_CROSSLINK)
|
||||||
blocks = []
|
blocks = []
|
||||||
for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH):
|
for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH):
|
||||||
|
|
|
@ -31,7 +31,7 @@ We define an "expansion" of an object as an object where a field in an object th
|
||||||
|
|
||||||
We define two expansions:
|
We define two expansions:
|
||||||
|
|
||||||
* `ExtendedBeaconState`, which is identical to a `BeaconState` except `latest_active_index_roots: List[Bytes32]` is replaced by `latest_active_indices: List[List[ValidatorIndex]]`, where `BeaconState.latest_active_index_roots[i] = hash_tree_root(ExtendedBeaconState.latest_active_indices[i])`.
|
* `ExtendedBeaconState`, which is identical to a `BeaconState` except `active_index_roots: List[Bytes32]` is replaced by `active_indices: List[List[ValidatorIndex]]`, where `BeaconState.active_index_roots[i] = hash_tree_root(ExtendedBeaconState.active_indices[i])`.
|
||||||
* `ExtendedBeaconBlock`, which is identical to a `BeaconBlock` except `state_root` is replaced with the corresponding `state: ExtendedBeaconState`.
|
* `ExtendedBeaconBlock`, which is identical to a `BeaconBlock` except `state_root` is replaced with the corresponding `state: ExtendedBeaconState`.
|
||||||
|
|
||||||
### `get_active_validator_indices`
|
### `get_active_validator_indices`
|
||||||
|
@ -40,10 +40,10 @@ Note that there is now a new way to compute `get_active_validator_indices`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_active_validator_indices(state: ExtendedBeaconState, epoch: Epoch) -> List[ValidatorIndex]:
|
def get_active_validator_indices(state: ExtendedBeaconState, epoch: Epoch) -> List[ValidatorIndex]:
|
||||||
return state.latest_active_indices[epoch % LATEST_ACTIVE_INDEX_ROOTS_LENGTH]
|
return state.active_indices[epoch % ACTIVE_INDEX_ROOTS_LENGTH]
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that it takes `state` instead of `state.validator_registry` as an argument. This does not affect its use in `get_shuffled_committee`, because `get_shuffled_committee` has access to the full `state` as one of its arguments.
|
Note that it takes `state` instead of `state.validators` as an argument. This does not affect its use in `get_shuffled_committee`, because `get_shuffled_committee` has access to the full `state` as one of its arguments.
|
||||||
|
|
||||||
|
|
||||||
### `MerklePartial`
|
### `MerklePartial`
|
||||||
|
@ -85,7 +85,7 @@ def get_period_data(block: ExtendedBeaconBlock, shard_id: Shard, later: bool) ->
|
||||||
return PeriodData(
|
return PeriodData(
|
||||||
validator_count,
|
validator_count,
|
||||||
generate_seed(block.state, period_start),
|
generate_seed(block.state, period_start),
|
||||||
[block.state.validator_registry[i] for i in indices],
|
[block.state.validators[i] for i in indices],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,8 @@ Since some clients are waiting for `libp2p` implementations in their respective
|
||||||
(
|
(
|
||||||
network_id: uint8
|
network_id: uint8
|
||||||
chain_id: uint64
|
chain_id: uint64
|
||||||
latest_finalized_root: bytes32
|
finalized_root: bytes32
|
||||||
latest_finalized_epoch: uint64
|
finalized_epoch: uint64
|
||||||
best_root: bytes32
|
best_root: bytes32
|
||||||
best_slot: uint64
|
best_slot: uint64
|
||||||
)
|
)
|
||||||
|
@ -107,7 +107,7 @@ Clients exchange `hello` messages upon connection, forming a two-phase handshake
|
||||||
Clients SHOULD immediately disconnect from one another following the handshake above under the following conditions:
|
Clients SHOULD immediately disconnect from one another following the handshake above under the following conditions:
|
||||||
|
|
||||||
1. If `network_id` belongs to a different chain, since the client definitionally cannot sync with this client.
|
1. If `network_id` belongs to a different chain, since the client definitionally cannot sync with this client.
|
||||||
2. If the `latest_finalized_root` shared by the peer is not in the client's chain at the expected epoch. For example, if Peer 1 in the diagram below has `(root, epoch)` of `(A, 5)` and Peer 2 has `(B, 3)`, Peer 1 would disconnect because it knows that `B` is not the root in their chain at epoch 3:
|
2. If the `finalized_root` shared by the peer is not in the client's chain at the expected epoch. For example, if Peer 1 in the diagram below has `(root, epoch)` of `(A, 5)` and Peer 2 has `(B, 3)`, Peer 1 would disconnect because it knows that `B` is not the root in their chain at epoch 3:
|
||||||
|
|
||||||
```
|
```
|
||||||
Root A
|
Root A
|
||||||
|
@ -136,7 +136,7 @@ Root B ^
|
||||||
+---+
|
+---+
|
||||||
```
|
```
|
||||||
|
|
||||||
Once the handshake completes, the client with the higher `latest_finalized_epoch` or `best_slot` (if the clients have equal `latest_finalized_epoch`s) SHOULD request beacon block roots from its counterparty via `beacon_block_roots` (i.e. RPC method `10`).
|
Once the handshake completes, the client with the higher `finalized_epoch` or `best_slot` (if the clients have equal `finalized_epoch`s) SHOULD request beacon block roots from its counterparty via `beacon_block_roots` (i.e. RPC method `10`).
|
||||||
|
|
||||||
### Goodbye
|
### Goodbye
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ Sanity tests to cover a series of one or more empty-slot transitions being proce
|
||||||
description: string -- description of test case, purely for debugging purposes
|
description: string -- description of test case, purely for debugging purposes
|
||||||
bls_setting: int -- see general test-format spec.
|
bls_setting: int -- see general test-format spec.
|
||||||
pre: BeaconState -- state before running through the transitions.
|
pre: BeaconState -- state before running through the transitions.
|
||||||
slots: N -- amount of slots to process, N being a positive numer.
|
slots: N -- amount of slots to process, N being a positive number.
|
||||||
post: BeaconState -- state after applying all the transitions.
|
post: BeaconState -- state after applying all the transitions.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -101,15 +101,15 @@ To submit a deposit:
|
||||||
* Let `signature` be the result of `bls_sign` of the `signing_root(deposit_data)` with `domain=bls_domain(DOMAIN_DEPOSIT)`. (Deposits are valid regardless of fork version, `bls_domain` will default to zeroes there).
|
* Let `signature` be the result of `bls_sign` of the `signing_root(deposit_data)` with `domain=bls_domain(DOMAIN_DEPOSIT)`. (Deposits are valid regardless of fork version, `bls_domain` will default to zeroes there).
|
||||||
* Send a transaction on the Ethereum 1.0 chain to `DEPOSIT_CONTRACT_ADDRESS` executing `def deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])` along with a deposit of `amount` Gwei.
|
* Send a transaction on the Ethereum 1.0 chain to `DEPOSIT_CONTRACT_ADDRESS` executing `def deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])` along with a deposit of `amount` Gwei.
|
||||||
|
|
||||||
*Note*: Deposits made for the same `pubkey` are treated as for the same validator. A singular `Validator` will be added to `state.validator_registry` with each additional deposit amount added to the validator's balance. A validator can only be activated when total deposits for the validator pubkey meet or exceed `MAX_EFFECTIVE_BALANCE`.
|
*Note*: Deposits made for the same `pubkey` are treated as for the same validator. A singular `Validator` will be added to `state.validators` with each additional deposit amount added to the validator's balance. A validator can only be activated when total deposits for the validator pubkey meet or exceed `MAX_EFFECTIVE_BALANCE`.
|
||||||
|
|
||||||
### Process deposit
|
### Process deposit
|
||||||
|
|
||||||
Deposits cannot be processed into the beacon chain until the Eth 1.0 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth 1.0 blocks (~4 hours) plus `ETH1_DATA_VOTING_PERIOD` epochs (~1.7 hours). Once the requisite Eth 1.0 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validator_registry` within an epoch or two. The validator is then in a queue to be activated.
|
Deposits cannot be processed into the beacon chain until the Eth 1.0 block in which they were deposited or any of its descendants is added to the beacon chain `state.eth1_data`. This takes _a minimum_ of `ETH1_FOLLOW_DISTANCE` Eth 1.0 blocks (~4 hours) plus `ETH1_DATA_VOTING_PERIOD` epochs (~1.7 hours). Once the requisite Eth 1.0 data is added, the deposit will normally be added to a beacon chain block and processed into the `state.validators` within an epoch or two. The validator is then in a queue to be activated.
|
||||||
|
|
||||||
### Validator index
|
### Validator index
|
||||||
|
|
||||||
Once a validator has been processed and added to the beacon state's `validator_registry`, the validator's `validator_index` is defined by the index into the registry at which the [`ValidatorRecord`](../core/0_beacon-chain.md#validator) contains the `pubkey` specified in the validator's deposit. A validator's `validator_index` is guaranteed to not change from the time of initial deposit until the validator exits and fully withdraws. This `validator_index` is used throughout the specification to dictate validator roles and responsibilities at any point and should be stored locally.
|
Once a validator has been processed and added to the beacon state's `validators`, the validator's `validator_index` is defined by the index into the registry at which the [`ValidatorRecord`](../core/0_beacon-chain.md#validator) contains the `pubkey` specified in the validator's deposit. A validator's `validator_index` is guaranteed to not change from the time of initial deposit until the validator exits and fully withdraws. This `validator_index` is used throughout the specification to dictate validator roles and responsibilities at any point and should be stored locally.
|
||||||
|
|
||||||
### Activation
|
### Activation
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ In normal operation, the validator is quickly activated at which point the valid
|
||||||
The function [`is_active_validator`](../core/0_beacon-chain.md#is_active_validator) can be used to check if a validator is active during a given epoch. Usage is as follows:
|
The function [`is_active_validator`](../core/0_beacon-chain.md#is_active_validator) can be used to check if a validator is active during a given epoch. Usage is as follows:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
validator = state.validator_registry[validator_index]
|
validator = state.validators[validator_index]
|
||||||
is_active = is_active_validator(validator, get_current_epoch(state))
|
is_active = is_active_validator(validator, get_current_epoch(state))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -221,10 +221,10 @@ epoch_signature = bls_sign(
|
||||||
|
|
||||||
##### Eth1 Data
|
##### Eth1 Data
|
||||||
|
|
||||||
`block.eth1_data` is a mechanism used by block proposers vote on a recent Ethereum 1.0 block hash and an associated deposit root found in the Ethereum 1.0 deposit contract. When consensus is formed, `state.latest_eth1_data` is updated, and validator deposits up to this root can be processed. The deposit root can be calculated by calling the `get_deposit_root()` function of the deposit contract using the post-state of the block hash.
|
`block.eth1_data` is a mechanism used by block proposers vote on a recent Ethereum 1.0 block hash and an associated deposit root found in the Ethereum 1.0 deposit contract. When consensus is formed, `state.eth1_data` is updated, and validator deposits up to this root can be processed. The deposit root can be calculated by calling the `get_deposit_root()` function of the deposit contract using the post-state of the block hash.
|
||||||
|
|
||||||
* Let `D` be the list of `Eth1DataVote` objects `vote` in `state.eth1_data_votes` where:
|
* Let `D` be the list of `Eth1DataVote` objects `vote` in `state.eth1_data_votes` where:
|
||||||
* `vote.eth1_data.block_hash` is the hash of an Eth 1.0 block that is (i) part of the canonical chain, (ii) >= `ETH1_FOLLOW_DISTANCE` blocks behind the head, and (iii) newer than `state.latest_eth1_data.block_hash`.
|
* `vote.eth1_data.block_hash` is the hash of an Eth 1.0 block that is (i) part of the canonical chain, (ii) >= `ETH1_FOLLOW_DISTANCE` blocks behind the head, and (iii) newer than `state.eth1_data.block_hash`.
|
||||||
* `vote.eth1_data.deposit_count` is the deposit count of the Eth 1.0 deposit contract at the block defined by `vote.eth1_data.block_hash`.
|
* `vote.eth1_data.deposit_count` is the deposit count of the Eth 1.0 deposit contract at the block defined by `vote.eth1_data.block_hash`.
|
||||||
* `vote.eth1_data.deposit_root` is the deposit root of the Eth 1.0 deposit contract at the block defined by `vote.eth1_data.block_hash`.
|
* `vote.eth1_data.deposit_root` is the deposit root of the Eth 1.0 deposit contract at the block defined by `vote.eth1_data.block_hash`.
|
||||||
* If `D` is empty:
|
* If `D` is empty:
|
||||||
|
@ -267,9 +267,9 @@ Up to `MAX_ATTESTATIONS` aggregate attestations can be included in the `block`.
|
||||||
|
|
||||||
##### Deposits
|
##### 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 [Eth 1.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).
|
If there are any unprocessed deposits for the existing `state.eth1_data` (i.e. `state.eth1_data.deposit_count > state.eth1_deposit_index`), then pending deposits _must_ be added to the block. The expected number of deposits is exactly `min(MAX_DEPOSITS, eth1_data.deposit_count - state.eth1_deposit_index)`. These [`deposits`](../core/0_beacon-chain.md#deposit) are constructed from the `Deposit` logs from the [Eth 1.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.
|
The `proof` for each deposit must be constructed against the deposit root contained in `state.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 `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.
|
||||||
|
|
||||||
##### Voluntary exits
|
##### Voluntary exits
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,15 @@ from gen_base import gen_runner, gen_suite, gen_typing
|
||||||
from py_ecc import bls
|
from py_ecc import bls
|
||||||
|
|
||||||
|
|
||||||
def int_to_hex(n: int) -> str:
|
F2Q_COEFF_LEN = 48
|
||||||
return '0x' + int_to_big_endian(n).hex()
|
G2_COMPRESSED_Z_LEN = 48
|
||||||
|
|
||||||
|
|
||||||
|
def int_to_hex(n: int, byte_length: int=None) -> str:
|
||||||
|
byte_value = int_to_big_endian(n)
|
||||||
|
if byte_length:
|
||||||
|
byte_value = byte_value.rjust(byte_length, b'\x00')
|
||||||
|
return '0x' + byte_value.hex()
|
||||||
|
|
||||||
|
|
||||||
def hex_to_int(x: str) -> int:
|
def hex_to_int(x: str) -> int:
|
||||||
|
@ -58,8 +65,8 @@ def hash_message(msg: bytes,
|
||||||
"""
|
"""
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
int_to_hex(fq2.coeffs[0]),
|
int_to_hex(fq2.coeffs[0], F2Q_COEFF_LEN),
|
||||||
int_to_hex(fq2.coeffs[1]),
|
int_to_hex(fq2.coeffs[1], F2Q_COEFF_LEN),
|
||||||
]
|
]
|
||||||
for fq2 in bls.utils.hash_to_G2(msg, domain)
|
for fq2 in bls.utils.hash_to_G2(msg, domain)
|
||||||
]
|
]
|
||||||
|
@ -75,8 +82,7 @@ def hash_message_compressed(msg: bytes, domain: int) -> Tuple[str, str]:
|
||||||
- Message hash as a compressed G2 point
|
- Message hash as a compressed G2 point
|
||||||
"""
|
"""
|
||||||
z1, z2 = bls.utils.compress_G2(bls.utils.hash_to_G2(msg, domain))
|
z1, z2 = bls.utils.compress_G2(bls.utils.hash_to_G2(msg, domain))
|
||||||
return [int_to_hex(z1), int_to_hex(z2)]
|
return [int_to_hex(z1, G2_COMPRESSED_Z_LEN), int_to_hex(z2, G2_COMPRESSED_Z_LEN)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@to_tuple
|
@to_tuple
|
||||||
|
|
|
@ -28,7 +28,7 @@ These tests are sanity tests, to verify if the spec itself is consistent.
|
||||||
|
|
||||||
#### Automated
|
#### Automated
|
||||||
|
|
||||||
Run `make test` from the root of the specs repository.
|
Run `make test` from the root of the specs repository (after running `make install_test` if have not before).
|
||||||
|
|
||||||
#### Manual
|
#### Manual
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ pytest --config=minimal eth2spec
|
||||||
```
|
```
|
||||||
Note the package-name, this is to locate the tests.
|
Note the package-name, this is to locate the tests.
|
||||||
|
|
||||||
|
### How to view code coverage report
|
||||||
|
|
||||||
|
Run `make open_cov` from the root of the specs repository after running `make test` to open the html code coverage report.
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
from eth2spec.utils.ssz import ssz_typing as spec_ssz
|
||||||
|
import ssz
|
||||||
|
|
||||||
|
|
||||||
|
def translate_typ(typ) -> ssz.BaseSedes:
|
||||||
|
"""
|
||||||
|
Translates a spec type to a Py-SSZ type description (sedes).
|
||||||
|
:param typ: The spec type, a class.
|
||||||
|
:return: The Py-SSZ equivalent.
|
||||||
|
"""
|
||||||
|
if spec_ssz.is_container_type(typ):
|
||||||
|
return ssz.Container(
|
||||||
|
[translate_typ(field_typ) for (field_name, field_typ) in typ.get_fields()])
|
||||||
|
elif spec_ssz.is_bytesn_type(typ):
|
||||||
|
return ssz.ByteVector(typ.length)
|
||||||
|
elif spec_ssz.is_bytes_type(typ):
|
||||||
|
return ssz.ByteList()
|
||||||
|
elif spec_ssz.is_vector_type(typ):
|
||||||
|
return ssz.Vector(translate_typ(spec_ssz.read_vector_elem_type(typ)), typ.length)
|
||||||
|
elif spec_ssz.is_list_type(typ):
|
||||||
|
return ssz.List(translate_typ(spec_ssz.read_list_elem_type(typ)))
|
||||||
|
elif spec_ssz.is_bool_type(typ):
|
||||||
|
return ssz.boolean
|
||||||
|
elif spec_ssz.is_uint_type(typ):
|
||||||
|
size = spec_ssz.uint_byte_size(typ)
|
||||||
|
if size == 1:
|
||||||
|
return ssz.uint8
|
||||||
|
elif size == 2:
|
||||||
|
return ssz.uint16
|
||||||
|
elif size == 4:
|
||||||
|
return ssz.uint32
|
||||||
|
elif size == 8:
|
||||||
|
return ssz.uint64
|
||||||
|
elif size == 16:
|
||||||
|
return ssz.uint128
|
||||||
|
elif size == 32:
|
||||||
|
return ssz.uint256
|
||||||
|
else:
|
||||||
|
raise TypeError("invalid uint size")
|
||||||
|
else:
|
||||||
|
raise TypeError("Type not supported: {}".format(typ))
|
||||||
|
|
||||||
|
|
||||||
|
def translate_value(value, typ):
|
||||||
|
"""
|
||||||
|
Translate a value output from Py-SSZ deserialization into the given spec type.
|
||||||
|
:param value: The PySSZ value
|
||||||
|
:param typ: The type from the spec to translate into
|
||||||
|
:return: the translated value
|
||||||
|
"""
|
||||||
|
if spec_ssz.is_uint_type(typ):
|
||||||
|
size = spec_ssz.uint_byte_size(typ)
|
||||||
|
if size == 1:
|
||||||
|
return spec_ssz.uint8(value)
|
||||||
|
elif size == 2:
|
||||||
|
return spec_ssz.uint16(value)
|
||||||
|
elif size == 4:
|
||||||
|
return spec_ssz.uint32(value)
|
||||||
|
elif size == 8:
|
||||||
|
# uint64 is default (TODO this is changing soon)
|
||||||
|
return value
|
||||||
|
elif size == 16:
|
||||||
|
return spec_ssz.uint128(value)
|
||||||
|
elif size == 32:
|
||||||
|
return spec_ssz.uint256(value)
|
||||||
|
else:
|
||||||
|
raise TypeError("invalid uint size")
|
||||||
|
elif spec_ssz.is_list_type(typ):
|
||||||
|
elem_typ = spec_ssz.read_elem_type(typ)
|
||||||
|
return [translate_value(elem, elem_typ) for elem in value]
|
||||||
|
elif spec_ssz.is_bool_type(typ):
|
||||||
|
return value
|
||||||
|
elif spec_ssz.is_vector_type(typ):
|
||||||
|
elem_typ = spec_ssz.read_elem_type(typ)
|
||||||
|
return typ(*(translate_value(elem, elem_typ) for elem in value))
|
||||||
|
elif spec_ssz.is_bytesn_type(typ):
|
||||||
|
return typ(value)
|
||||||
|
elif spec_ssz.is_bytes_type(typ):
|
||||||
|
return value
|
||||||
|
elif spec_ssz.is_container_type(typ):
|
||||||
|
return typ(**{f_name: translate_value(f_val, f_typ) for (f_name, f_val, f_typ)
|
||||||
|
in zip(typ.get_field_names(), value, typ.get_field_types())})
|
||||||
|
else:
|
||||||
|
raise TypeError("Type not supported: {}".format(typ))
|
|
@ -0,0 +1,33 @@
|
||||||
|
from eth2spec.fuzzing.decoder import translate_typ, translate_value
|
||||||
|
from eth2spec.phase0 import spec
|
||||||
|
from eth2spec.utils.ssz import ssz_impl as spec_ssz_impl
|
||||||
|
from random import Random
|
||||||
|
from eth2spec.debug import random_value
|
||||||
|
|
||||||
|
|
||||||
|
def test_decoder():
|
||||||
|
rng = Random(123)
|
||||||
|
|
||||||
|
# check these types only, Block covers a lot of operation types already.
|
||||||
|
for typ in [spec.BeaconBlock, spec.BeaconState, spec.IndexedAttestation, spec.AttestationDataAndCustodyBit]:
|
||||||
|
# create a random pyspec value
|
||||||
|
original = random_value.get_random_ssz_object(rng, typ, 100, 10,
|
||||||
|
mode=random_value.RandomizationMode.mode_random,
|
||||||
|
chaos=True)
|
||||||
|
# serialize it, using pyspec
|
||||||
|
pyspec_data = spec_ssz_impl.serialize(original)
|
||||||
|
# get the py-ssz type for it
|
||||||
|
block_sedes = translate_typ(typ)
|
||||||
|
# try decoding using the py-ssz type
|
||||||
|
raw_value = block_sedes.deserialize(pyspec_data)
|
||||||
|
|
||||||
|
# serialize it using py-ssz
|
||||||
|
pyssz_data = block_sedes.serialize(raw_value)
|
||||||
|
# now check if the serialized form is equal. If so, we confirmed decoding and encoding to work.
|
||||||
|
assert pyspec_data == pyssz_data
|
||||||
|
|
||||||
|
# now translate the py-ssz value in a pyspec-value
|
||||||
|
block = translate_value(raw_value, typ)
|
||||||
|
|
||||||
|
# and see if the hash-tree-root of the original matches the hash-tree-root of the decoded & translated value.
|
||||||
|
assert spec_ssz_impl.hash_tree_root(original) == spec_ssz_impl.hash_tree_root(block)
|
|
@ -57,7 +57,7 @@ def build_empty_block(spec, state, slot=None, signed=False):
|
||||||
slot = state.slot
|
slot = state.slot
|
||||||
empty_block = spec.BeaconBlock()
|
empty_block = spec.BeaconBlock()
|
||||||
empty_block.slot = slot
|
empty_block.slot = slot
|
||||||
empty_block.body.eth1_data.deposit_count = state.deposit_index
|
empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
|
||||||
previous_block_header = deepcopy(state.latest_block_header)
|
previous_block_header = deepcopy(state.latest_block_header)
|
||||||
if previous_block_header.state_root == spec.ZERO_HASH:
|
if previous_block_header.state_root == spec.ZERO_HASH:
|
||||||
previous_block_header.state_root = state.hash_tree_root()
|
previous_block_header.state_root = state.hash_tree_root()
|
||||||
|
|
|
@ -58,7 +58,7 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c
|
||||||
"""
|
"""
|
||||||
Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount.
|
Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount.
|
||||||
"""
|
"""
|
||||||
pre_validator_count = len(state.validator_registry)
|
pre_validator_count = len(state.validators)
|
||||||
# fill previous deposits with zero-hash
|
# fill previous deposits with zero-hash
|
||||||
deposit_data_leaves = [spec.ZERO_HASH] * pre_validator_count
|
deposit_data_leaves = [spec.ZERO_HASH] * pre_validator_count
|
||||||
|
|
||||||
|
@ -80,6 +80,6 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c
|
||||||
signed,
|
signed,
|
||||||
)
|
)
|
||||||
|
|
||||||
state.latest_eth1_data.deposit_root = root
|
state.eth1_data.deposit_root = root
|
||||||
state.latest_eth1_data.deposit_count = len(deposit_data_leaves)
|
state.eth1_data.deposit_count = len(deposit_data_leaves)
|
||||||
return deposit
|
return deposit
|
||||||
|
|
|
@ -22,8 +22,8 @@ def create_genesis_state(spec, num_validators):
|
||||||
|
|
||||||
state = spec.BeaconState(
|
state = spec.BeaconState(
|
||||||
genesis_time=0,
|
genesis_time=0,
|
||||||
deposit_index=num_validators,
|
eth1_deposit_index=num_validators,
|
||||||
latest_eth1_data=spec.Eth1Data(
|
eth1_data=spec.Eth1Data(
|
||||||
deposit_root=deposit_root,
|
deposit_root=deposit_root,
|
||||||
deposit_count=num_validators,
|
deposit_count=num_validators,
|
||||||
block_hash=spec.ZERO_HASH,
|
block_hash=spec.ZERO_HASH,
|
||||||
|
@ -32,16 +32,16 @@ def create_genesis_state(spec, num_validators):
|
||||||
# We "hack" in the initial validators,
|
# We "hack" in the initial validators,
|
||||||
# as it is much faster than creating and processing genesis deposits for every single test case.
|
# as it is much faster than creating and processing genesis deposits for every single test case.
|
||||||
state.balances = [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
state.balances = [spec.MAX_EFFECTIVE_BALANCE] * num_validators
|
||||||
state.validator_registry = [build_mock_validator(spec, i, state.balances[i]) for i in range(num_validators)]
|
state.validators = [build_mock_validator(spec, i, state.balances[i]) for i in range(num_validators)]
|
||||||
|
|
||||||
# Process genesis activations
|
# Process genesis activations
|
||||||
for validator in state.validator_registry:
|
for validator in state.validators:
|
||||||
if validator.effective_balance >= spec.MAX_EFFECTIVE_BALANCE:
|
if validator.effective_balance >= spec.MAX_EFFECTIVE_BALANCE:
|
||||||
validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
|
validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
|
||||||
validator.activation_epoch = spec.GENESIS_EPOCH
|
validator.activation_epoch = spec.GENESIS_EPOCH
|
||||||
|
|
||||||
genesis_active_index_root = hash_tree_root(spec.get_active_validator_indices(state, spec.GENESIS_EPOCH))
|
genesis_active_index_root = hash_tree_root(spec.get_active_validator_indices(state, spec.GENESIS_EPOCH))
|
||||||
for index in range(spec.LATEST_ACTIVE_INDEX_ROOTS_LENGTH):
|
for index in range(spec.ACTIVE_INDEX_ROOTS_LENGTH):
|
||||||
state.latest_active_index_roots[index] = genesis_active_index_root
|
state.active_index_roots[index] = genesis_active_index_root
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -7,7 +7,7 @@ from eth2spec.test.helpers.keys import pubkey_to_privkey
|
||||||
def get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=False):
|
def get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=False):
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
slot = state.slot
|
slot = state.slot
|
||||||
|
|
||||||
header_1 = spec.BeaconBlockHeader(
|
header_1 = spec.BeaconBlockHeader(
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from eth2spec.test.helpers.block import sign_block
|
||||||
|
|
||||||
|
|
||||||
def get_balance(state, index):
|
def get_balance(state, index):
|
||||||
return state.balances[index]
|
return state.balances[index]
|
||||||
|
|
||||||
|
@ -22,4 +25,14 @@ def get_state_root(spec, state, slot) -> bytes:
|
||||||
Return the state root at a recent ``slot``.
|
Return the state root at a recent ``slot``.
|
||||||
"""
|
"""
|
||||||
assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT
|
assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT
|
||||||
return state.latest_state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT]
|
return state.state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT]
|
||||||
|
|
||||||
|
|
||||||
|
def state_transition_and_sign_block(spec, state, block):
|
||||||
|
"""
|
||||||
|
State transition via the provided ``block``
|
||||||
|
then package the block with the state root and signature.
|
||||||
|
"""
|
||||||
|
spec.state_transition(state, block)
|
||||||
|
block.state_root = state.hash_tree_root()
|
||||||
|
sign_block(spec, state, block)
|
||||||
|
|
|
@ -31,7 +31,7 @@ def get_valid_transfer(spec, state, slot=None, sender_index=None, amount=None, f
|
||||||
sign_transfer(spec, state, transfer, transfer_privkey)
|
sign_transfer(spec, state, transfer, transfer_privkey)
|
||||||
|
|
||||||
# ensure withdrawal_credentials reproducible
|
# ensure withdrawal_credentials reproducible
|
||||||
state.validator_registry[transfer.sender].withdrawal_credentials = (
|
state.validators[transfer.sender].withdrawal_credentials = (
|
||||||
spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(transfer.pubkey)[1:]
|
spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(transfer.pubkey)[1:]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True)
|
||||||
# Process slashing
|
# Process slashing
|
||||||
spec.process_attester_slashing(state, attester_slashing)
|
spec.process_attester_slashing(state, attester_slashing)
|
||||||
|
|
||||||
slashed_validator = state.validator_registry[slashed_index]
|
slashed_validator = state.validators[slashed_index]
|
||||||
|
|
||||||
# Check slashing
|
# Check slashing
|
||||||
assert slashed_validator.slashed
|
assert slashed_validator.slashed
|
||||||
|
@ -135,7 +135,7 @@ def test_participants_already_slashed(spec, state):
|
||||||
attestation_1 = attester_slashing.attestation_1
|
attestation_1 = attester_slashing.attestation_1
|
||||||
validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
|
validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
|
||||||
for index in validator_indices:
|
for index in validator_indices:
|
||||||
state.validator_registry[index].slashed = True
|
state.validators[index].slashed = True
|
||||||
|
|
||||||
yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
|
yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ def test_proposer_slashed(spec, state):
|
||||||
proposer_index = spec.get_beacon_proposer_index(stub_state)
|
proposer_index = spec.get_beacon_proposer_index(stub_state)
|
||||||
|
|
||||||
# set proposer to slashed
|
# set proposer to slashed
|
||||||
state.validator_registry[proposer_index].slashed = True
|
state.validators[proposer_index].slashed = True
|
||||||
|
|
||||||
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef
|
||||||
- post-state ('post').
|
- post-state ('post').
|
||||||
If ``valid == False``, run expecting ``AssertionError``
|
If ``valid == False``, run expecting ``AssertionError``
|
||||||
"""
|
"""
|
||||||
pre_validator_count = len(state.validator_registry)
|
pre_validator_count = len(state.validators)
|
||||||
pre_balance = 0
|
pre_balance = 0
|
||||||
if validator_index < pre_validator_count:
|
if validator_index < pre_validator_count:
|
||||||
pre_balance = get_balance(state, validator_index)
|
pre_balance = get_balance(state, validator_index)
|
||||||
|
@ -34,29 +34,29 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
if not effective:
|
if not effective:
|
||||||
assert len(state.validator_registry) == pre_validator_count
|
assert len(state.validators) == pre_validator_count
|
||||||
assert len(state.balances) == pre_validator_count
|
assert len(state.balances) == pre_validator_count
|
||||||
if validator_index < pre_validator_count:
|
if validator_index < pre_validator_count:
|
||||||
assert get_balance(state, validator_index) == pre_balance
|
assert get_balance(state, validator_index) == pre_balance
|
||||||
else:
|
else:
|
||||||
if validator_index < pre_validator_count:
|
if validator_index < pre_validator_count:
|
||||||
# top-up
|
# top-up
|
||||||
assert len(state.validator_registry) == pre_validator_count
|
assert len(state.validators) == pre_validator_count
|
||||||
assert len(state.balances) == pre_validator_count
|
assert len(state.balances) == pre_validator_count
|
||||||
else:
|
else:
|
||||||
# new validator
|
# new validator
|
||||||
assert len(state.validator_registry) == pre_validator_count + 1
|
assert len(state.validators) == pre_validator_count + 1
|
||||||
assert len(state.balances) == pre_validator_count + 1
|
assert len(state.balances) == pre_validator_count + 1
|
||||||
assert get_balance(state, validator_index) == pre_balance + deposit.data.amount
|
assert get_balance(state, validator_index) == pre_balance + deposit.data.amount
|
||||||
|
|
||||||
assert state.deposit_index == state.latest_eth1_data.deposit_count
|
assert state.eth1_deposit_index == state.eth1_data.deposit_count
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_new_deposit(spec, state):
|
def test_new_deposit(spec, state):
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
validator_index = len(state.validator_registry)
|
validator_index = len(state.validators)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ def test_new_deposit(spec, state):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_invalid_sig_new_deposit(spec, state):
|
def test_invalid_sig_new_deposit(spec, state):
|
||||||
# fresh deposit = next validator index = validator appended to registry
|
# fresh deposit = next validator index = validator appended to registry
|
||||||
validator_index = len(state.validator_registry)
|
validator_index = len(state.validators)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||||
yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False)
|
yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False)
|
||||||
|
@ -117,12 +117,12 @@ def test_invalid_withdrawal_credentials_top_up(spec, state):
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_wrong_index(spec, state):
|
def test_wrong_index(spec, state):
|
||||||
validator_index = len(state.validator_registry)
|
validator_index = len(state.validators)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||||
|
|
||||||
# mess up deposit_index
|
# mess up eth1_deposit_index
|
||||||
deposit.index = state.deposit_index + 1
|
deposit.index = state.eth1_deposit_index + 1
|
||||||
|
|
||||||
sign_deposit_data(spec, state, deposit.data, privkeys[validator_index])
|
sign_deposit_data(spec, state, deposit.data, privkeys[validator_index])
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ def test_wrong_index(spec, state):
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_wrong_deposit_for_deposit_count(spec, state):
|
def test_wrong_deposit_for_deposit_count(spec, state):
|
||||||
deposit_data_leaves = [spec.ZERO_HASH] * len(state.validator_registry)
|
deposit_data_leaves = [spec.ZERO_HASH] * len(state.validators)
|
||||||
|
|
||||||
# build root for deposit_1
|
# build root for deposit_1
|
||||||
index_1 = len(deposit_data_leaves)
|
index_1 = len(deposit_data_leaves)
|
||||||
|
@ -166,8 +166,8 @@ def test_wrong_deposit_for_deposit_count(spec, state):
|
||||||
)
|
)
|
||||||
|
|
||||||
# state has root for deposit_2 but is at deposit_count for deposit_1
|
# state has root for deposit_2 but is at deposit_count for deposit_1
|
||||||
state.latest_eth1_data.deposit_root = root_2
|
state.eth1_data.deposit_root = root_2
|
||||||
state.latest_eth1_data.deposit_count = deposit_count_1
|
state.eth1_data.deposit_count = deposit_count_1
|
||||||
|
|
||||||
yield from run_deposit_processing(spec, state, deposit_2, index_2, valid=False)
|
yield from run_deposit_processing(spec, state, deposit_2, index_2, valid=False)
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ def test_wrong_deposit_for_deposit_count(spec, state):
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_bad_merkle_proof(spec, state):
|
def test_bad_merkle_proof(spec, state):
|
||||||
validator_index = len(state.validator_registry)
|
validator_index = len(state.validators)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True)
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
# check if slashed
|
# check if slashed
|
||||||
slashed_validator = state.validator_registry[proposer_slashing.proposer_index]
|
slashed_validator = state.validators[proposer_slashing.proposer_index]
|
||||||
assert slashed_validator.slashed
|
assert slashed_validator.slashed
|
||||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
@ -77,7 +77,7 @@ def test_invalid_sig_1_and_2(spec, state):
|
||||||
def test_invalid_proposer_index(spec, state):
|
def test_invalid_proposer_index(spec, state):
|
||||||
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
||||||
# Index just too high (by 1)
|
# Index just too high (by 1)
|
||||||
proposer_slashing.proposer_index = len(state.validator_registry)
|
proposer_slashing.proposer_index = len(state.validators)
|
||||||
|
|
||||||
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ def test_proposer_is_not_activated(spec, state):
|
||||||
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
||||||
|
|
||||||
# set proposer to be not active yet
|
# set proposer to be not active yet
|
||||||
state.validator_registry[proposer_slashing.proposer_index].activation_epoch = spec.get_current_epoch(state) + 1
|
state.validators[proposer_slashing.proposer_index].activation_epoch = spec.get_current_epoch(state) + 1
|
||||||
|
|
||||||
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ def test_proposer_is_slashed(spec, state):
|
||||||
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
||||||
|
|
||||||
# set proposer to slashed
|
# set proposer to slashed
|
||||||
state.validator_registry[proposer_slashing.proposer_index].slashed = True
|
state.validators[proposer_slashing.proposer_index].slashed = True
|
||||||
|
|
||||||
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
||||||
|
|
||||||
|
@ -137,6 +137,6 @@ def test_proposer_is_withdrawn(spec, state):
|
||||||
# set proposer withdrawable_epoch in past
|
# set proposer withdrawable_epoch in past
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
proposer_index = proposer_slashing.proposer_index
|
proposer_index = proposer_slashing.proposer_index
|
||||||
state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1
|
state.validators[proposer_index].withdrawable_epoch = current_epoch - 1
|
||||||
|
|
||||||
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
|
||||||
|
|
|
@ -41,7 +41,7 @@ def run_transfer_processing(spec, state, transfer, valid=True):
|
||||||
def test_success_non_activated(spec, state):
|
def test_success_non_activated(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, signed=True)
|
transfer = get_valid_transfer(spec, state, signed=True)
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer)
|
yield from run_transfer_processing(spec, state, transfer)
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def test_success_withdrawable(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, signed=True)
|
transfer = get_valid_transfer(spec, state, signed=True)
|
||||||
|
|
||||||
# withdrawable_epoch in past so can transfer
|
# withdrawable_epoch in past so can transfer
|
||||||
state.validator_registry[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1
|
state.validators[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer)
|
yield from run_transfer_processing(spec, state, transfer)
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ def test_success_active_above_max_effective_fee(spec, state):
|
||||||
def test_invalid_signature(spec, state):
|
def test_invalid_signature(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state)
|
transfer = get_valid_transfer(spec, state)
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ def test_active_but_transfer_past_effective_balance(spec, state):
|
||||||
def test_incorrect_slot(spec, state):
|
def test_incorrect_slot(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, slot=state.slot + 1, signed=True)
|
transfer = get_valid_transfer(spec, state, slot=state.slot + 1, signed=True)
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ def test_insufficient_balance_for_fee(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=0, fee=1, signed=True)
|
transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=0, fee=1, signed=True)
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ def test_insufficient_balance(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=1, fee=0, signed=True)
|
transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=1, fee=0, signed=True)
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ def test_no_dust_sender(spec, state):
|
||||||
)
|
)
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ def test_no_dust_recipient(spec, state):
|
||||||
state.balances[transfer.recipient] = 0
|
state.balances[transfer.recipient] = 0
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
||||||
|
@ -176,9 +176,9 @@ def test_no_dust_recipient(spec, state):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_invalid_pubkey(spec, state):
|
def test_invalid_pubkey(spec, state):
|
||||||
transfer = get_valid_transfer(spec, state, signed=True)
|
transfer = get_valid_transfer(spec, state, signed=True)
|
||||||
state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
|
state.validators[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
yield from run_transfer_processing(spec, state, transfer, False)
|
yield from run_transfer_processing(spec, state, transfer, False)
|
||||||
|
|
|
@ -21,14 +21,14 @@ def run_voluntary_exit_processing(spec, state, voluntary_exit, valid=True):
|
||||||
yield 'post', None
|
yield 'post', None
|
||||||
return
|
return
|
||||||
|
|
||||||
pre_exit_epoch = state.validator_registry[validator_index].exit_epoch
|
pre_exit_epoch = state.validators[validator_index].exit_epoch
|
||||||
|
|
||||||
spec.process_voluntary_exit(state, voluntary_exit)
|
spec.process_voluntary_exit(state, voluntary_exit)
|
||||||
|
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||||
assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
|
@ -39,7 +39,7 @@ def test_success(spec, state):
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey, signed=True)
|
voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey, signed=True)
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def test_invalid_signature(spec, state):
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey)
|
voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey)
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ def test_success_exit_queue(spec, state):
|
||||||
# Prepare a bunch of exits, based on the current state
|
# Prepare a bunch of exits, based on the current state
|
||||||
exit_queue = []
|
exit_queue = []
|
||||||
for index in initial_indices:
|
for index in initial_indices:
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[index].pubkey]
|
||||||
exit_queue.append(build_voluntary_exit(
|
exit_queue.append(build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
state,
|
state,
|
||||||
|
@ -94,7 +94,7 @@ def test_success_exit_queue(spec, state):
|
||||||
|
|
||||||
# exit an additional validator
|
# exit an additional validator
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
state,
|
state,
|
||||||
|
@ -109,8 +109,8 @@ def test_success_exit_queue(spec, state):
|
||||||
yield from run_voluntary_exit_processing(spec, state, voluntary_exit)
|
yield from run_voluntary_exit_processing(spec, state, voluntary_exit)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
state.validator_registry[validator_index].exit_epoch ==
|
state.validators[validator_index].exit_epoch ==
|
||||||
state.validator_registry[initial_indices[0]].exit_epoch + 1
|
state.validators[initial_indices[0]].exit_epoch + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ def test_validator_exit_in_future(spec, state):
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
|
@ -146,7 +146,7 @@ def test_validator_invalid_validator_index(spec, state):
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
|
@ -156,7 +156,7 @@ def test_validator_invalid_validator_index(spec, state):
|
||||||
privkey,
|
privkey,
|
||||||
signed=False,
|
signed=False,
|
||||||
)
|
)
|
||||||
voluntary_exit.validator_index = len(state.validator_registry)
|
voluntary_exit.validator_index = len(state.validators)
|
||||||
sign_voluntary_exit(spec, state, voluntary_exit, privkey)
|
sign_voluntary_exit(spec, state, voluntary_exit, privkey)
|
||||||
|
|
||||||
yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False)
|
yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False)
|
||||||
|
@ -167,9 +167,9 @@ def test_validator_invalid_validator_index(spec, state):
|
||||||
def test_validator_not_active(spec, state):
|
def test_validator_not_active(spec, state):
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
# build and test voluntary exit
|
# build and test voluntary exit
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
|
@ -192,10 +192,10 @@ def test_validator_already_exited(spec, state):
|
||||||
|
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
# but validator already has exited
|
# but validator already has exited
|
||||||
state.validator_registry[validator_index].exit_epoch = current_epoch + 2
|
state.validators[validator_index].exit_epoch = current_epoch + 2
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
|
@ -214,7 +214,7 @@ def test_validator_already_exited(spec, state):
|
||||||
def test_validator_not_active_long_enough(spec, state):
|
def test_validator_not_active_long_enough(spec, state):
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
|
||||||
privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
|
privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
|
||||||
|
|
||||||
voluntary_exit = build_voluntary_exit(
|
voluntary_exit = build_voluntary_exit(
|
||||||
spec,
|
spec,
|
||||||
|
@ -226,7 +226,7 @@ def test_validator_not_active_long_enough(spec, state):
|
||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
current_epoch - state.validator_registry[validator_index].activation_epoch <
|
current_epoch - state.validators[validator_index].activation_epoch <
|
||||||
spec.PERSISTENT_COMMITTEE_PERIOD
|
spec.PERSISTENT_COMMITTEE_PERIOD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ from copy import deepcopy
|
||||||
from eth2spec.test.context import spec_state_test, with_all_phases
|
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_epoch,
|
next_epoch,
|
||||||
next_slot
|
next_slot,
|
||||||
|
state_transition_and_sign_block,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.block import apply_empty_block, sign_block
|
from eth2spec.test.helpers.block import apply_empty_block, sign_block
|
||||||
from eth2spec.test.helpers.attestations import (
|
from eth2spec.test.helpers.attestations import (
|
||||||
|
@ -27,11 +28,14 @@ def run_process_crosslinks(spec, state, valid=True):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.slot = slot
|
block.slot = slot
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
# cache state before epoch transition
|
# cache state before epoch transition
|
||||||
spec.process_slot(state)
|
spec.process_slot(state)
|
||||||
|
|
||||||
|
# process components of epoch transition before processing crosslinks
|
||||||
|
spec.process_justification_and_finalization(state)
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
spec.process_crosslinks(state)
|
spec.process_crosslinks(state)
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from eth2spec.phase0.spec import state_transition
|
|
||||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
|
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
|
||||||
from eth2spec.test.helpers.state import next_epoch
|
from eth2spec.test.helpers.state import next_epoch, state_transition_and_sign_block
|
||||||
from eth2spec.test.context import spec_state_test, with_all_phases
|
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ def run_process_registry_updates(spec, state, valid=True):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.slot = slot
|
block.slot = slot
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
# cache state before epoch transition
|
# cache state before epoch transition
|
||||||
spec.process_slot(state)
|
spec.process_slot(state)
|
||||||
|
@ -35,23 +34,23 @@ def run_process_registry_updates(spec, state, valid=True):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_activation(spec, state):
|
def test_activation(spec, state):
|
||||||
index = 0
|
index = 0
|
||||||
assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
|
assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
|
||||||
|
|
||||||
# Mock a new deposit
|
# Mock a new deposit
|
||||||
state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
state.validators[index].activation_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
state.validators[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
|
||||||
assert not spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
|
assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
|
||||||
|
|
||||||
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
||||||
next_epoch(spec, state)
|
next_epoch(spec, state)
|
||||||
|
|
||||||
yield from run_process_registry_updates(spec, state)
|
yield from run_process_registry_updates(spec, state)
|
||||||
|
|
||||||
assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
|
assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH
|
assert state.validators[index].activation_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
assert spec.is_active_validator(
|
assert spec.is_active_validator(
|
||||||
state.validator_registry[index],
|
state.validators[index],
|
||||||
spec.get_current_epoch(state),
|
spec.get_current_epoch(state),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,19 +59,19 @@ def test_activation(spec, state):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_ejection(spec, state):
|
def test_ejection(spec, state):
|
||||||
index = 0
|
index = 0
|
||||||
assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
|
assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
|
||||||
assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
assert state.validators[index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
# Mock an ejection
|
# Mock an ejection
|
||||||
state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE
|
state.validators[index].effective_balance = spec.EJECTION_BALANCE
|
||||||
|
|
||||||
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
|
||||||
next_epoch(spec, state)
|
next_epoch(spec, state)
|
||||||
|
|
||||||
yield from run_process_registry_updates(spec, state)
|
yield from run_process_registry_updates(spec, state)
|
||||||
|
|
||||||
assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH
|
assert state.validators[index].exit_epoch != spec.FAR_FUTURE_EPOCH
|
||||||
assert not spec.is_active_validator(
|
assert not spec.is_active_validator(
|
||||||
state.validator_registry[index],
|
state.validators[index],
|
||||||
spec.get_current_epoch(state),
|
spec.get_current_epoch(state),
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,7 +24,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v
|
||||||
|
|
||||||
spec.process_early_derived_secret_reveal(state, randao_key_reveal)
|
spec.process_early_derived_secret_reveal(state, randao_key_reveal)
|
||||||
|
|
||||||
slashed_validator = state.validator_registry[randao_key_reveal.revealed_index]
|
slashed_validator = state.validators[randao_key_reveal.revealed_index]
|
||||||
|
|
||||||
if randao_key_reveal.epoch >= spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING:
|
if randao_key_reveal.epoch >= spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING:
|
||||||
assert slashed_validator.slashed
|
assert slashed_validator.slashed
|
||||||
|
@ -111,7 +111,7 @@ def test_double_reveal(spec, state):
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_revealer_is_slashed(spec, state):
|
def test_revealer_is_slashed(spec, state):
|
||||||
randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state))
|
randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state))
|
||||||
state.validator_registry[randao_key_reveal.revealed_index].slashed = True
|
state.validators[randao_key_reveal.revealed_index].slashed = True
|
||||||
|
|
||||||
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
|
yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ from typing import List
|
||||||
from eth2spec.utils.ssz.ssz_impl import signing_root
|
from eth2spec.utils.ssz.ssz_impl import signing_root
|
||||||
from eth2spec.utils.bls import bls_sign
|
from eth2spec.utils.bls import bls_sign
|
||||||
|
|
||||||
from eth2spec.test.helpers.state import get_balance
|
from eth2spec.test.helpers.state import get_balance, state_transition_and_sign_block
|
||||||
# from eth2spec.test.helpers.transfers import get_valid_transfer
|
# from eth2spec.test.helpers.transfers import get_valid_transfer
|
||||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
|
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, sign_block
|
||||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
||||||
|
@ -13,11 +13,10 @@ from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing
|
||||||
from eth2spec.test.helpers.attestations import get_valid_attestation
|
from eth2spec.test.helpers.attestations import get_valid_attestation
|
||||||
from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
from eth2spec.test.helpers.deposits import prepare_state_and_deposit
|
||||||
|
|
||||||
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases
|
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@never_bls
|
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_empty_block_transition(spec, state):
|
def test_empty_block_transition(spec, state):
|
||||||
pre_slot = state.slot
|
pre_slot = state.slot
|
||||||
|
@ -26,17 +25,18 @@ def test_empty_block_transition(spec, state):
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert len(state.eth1_data_votes) == pre_eth1_votes + 1
|
assert len(state.eth1_data_votes) == pre_eth1_votes + 1
|
||||||
assert spec.get_block_root_at_slot(state, pre_slot) == block.parent_root
|
assert spec.get_block_root_at_slot(state, pre_slot) == block.parent_root
|
||||||
|
assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.ZERO_HASH
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@never_bls
|
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_skipped_slots(spec, state):
|
def test_skipped_slots(spec, state):
|
||||||
pre_slot = state.slot
|
pre_slot = state.slot
|
||||||
|
@ -45,12 +45,14 @@ def test_skipped_slots(spec, state):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.slot += 3
|
block.slot += 3
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert state.slot == block.slot
|
assert state.slot == block.slot
|
||||||
|
assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.ZERO_HASH
|
||||||
for slot in range(pre_slot, state.slot):
|
for slot in range(pre_slot, state.slot):
|
||||||
assert spec.get_block_root_at_slot(state, slot) == block.parent_root
|
assert spec.get_block_root_at_slot(state, slot) == block.parent_root
|
||||||
|
|
||||||
|
@ -64,9 +66,10 @@ def test_empty_epoch_transition(spec, state):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.slot += spec.SLOTS_PER_EPOCH
|
block.slot += spec.SLOTS_PER_EPOCH
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert state.slot == block.slot
|
assert state.slot == block.slot
|
||||||
|
@ -84,14 +87,15 @@ def test_empty_epoch_transition(spec, state):
|
||||||
# block = build_empty_block_for_next_slot(spec, state)
|
# block = build_empty_block_for_next_slot(spec, state)
|
||||||
# block.slot += spec.SLOTS_PER_EPOCH * 5
|
# block.slot += spec.SLOTS_PER_EPOCH * 5
|
||||||
# sign_block(spec, state, block, proposer_index=0)
|
# sign_block(spec, state, block, proposer_index=0)
|
||||||
# yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
# spec.state_transition(state, block)
|
# state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
# yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
# yield 'post', state
|
# yield 'post', state
|
||||||
|
|
||||||
# assert state.slot == block.slot
|
# assert state.slot == block.slot
|
||||||
# assert state.finalized_epoch < spec.get_current_epoch(state) - 4
|
# assert state.finalized_epoch < spec.get_current_epoch(state) - 4
|
||||||
# for index in range(len(state.validator_registry)):
|
# for index in range(len(state.validators)):
|
||||||
# assert get_balance(state, index) < get_balance(pre_state, index)
|
# assert get_balance(state, index) < get_balance(pre_state, index)
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +107,7 @@ def test_proposer_slashing(spec, state):
|
||||||
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
|
||||||
validator_index = proposer_slashing.proposer_index
|
validator_index = proposer_slashing.proposer_index
|
||||||
|
|
||||||
assert not state.validator_registry[validator_index].slashed
|
assert not state.validators[validator_index].slashed
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
|
@ -113,13 +117,14 @@ def test_proposer_slashing(spec, state):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.body.proposer_slashings.append(proposer_slashing)
|
block.body.proposer_slashings.append(proposer_slashing)
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
# check if slashed
|
# check if slashed
|
||||||
slashed_validator = state.validator_registry[validator_index]
|
slashed_validator = state.validators[validator_index]
|
||||||
assert slashed_validator.slashed
|
assert slashed_validator.slashed
|
||||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
@ -137,7 +142,7 @@ def test_attester_slashing(spec, state):
|
||||||
validator_index = (attester_slashing.attestation_1.custody_bit_0_indices +
|
validator_index = (attester_slashing.attestation_1.custody_bit_0_indices +
|
||||||
attester_slashing.attestation_1.custody_bit_1_indices)[0]
|
attester_slashing.attestation_1.custody_bit_1_indices)[0]
|
||||||
|
|
||||||
assert not state.validator_registry[validator_index].slashed
|
assert not state.validators[validator_index].slashed
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
|
@ -147,12 +152,13 @@ def test_attester_slashing(spec, state):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.body.attester_slashings.append(attester_slashing)
|
block.body.attester_slashings.append(attester_slashing)
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
slashed_validator = state.validator_registry[validator_index]
|
slashed_validator = state.validators[validator_index]
|
||||||
assert slashed_validator.slashed
|
assert slashed_validator.slashed
|
||||||
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
@ -172,10 +178,10 @@ def test_attester_slashing(spec, state):
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_deposit_in_block(spec, state):
|
def test_deposit_in_block(spec, state):
|
||||||
initial_registry_len = len(state.validator_registry)
|
initial_registry_len = len(state.validators)
|
||||||
initial_balances_len = len(state.balances)
|
initial_balances_len = len(state.balances)
|
||||||
|
|
||||||
validator_index = len(state.validator_registry)
|
validator_index = len(state.validators)
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE
|
amount = spec.MAX_EFFECTIVE_BALANCE
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
|
||||||
|
|
||||||
|
@ -185,15 +191,15 @@ def test_deposit_in_block(spec, state):
|
||||||
block.body.deposits.append(deposit)
|
block.body.deposits.append(deposit)
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
|
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert len(state.validator_registry) == initial_registry_len + 1
|
assert len(state.validators) == initial_registry_len + 1
|
||||||
assert len(state.balances) == initial_balances_len + 1
|
assert len(state.balances) == initial_balances_len + 1
|
||||||
assert get_balance(state, validator_index) == spec.MAX_EFFECTIVE_BALANCE
|
assert get_balance(state, validator_index) == spec.MAX_EFFECTIVE_BALANCE
|
||||||
assert state.validator_registry[validator_index].pubkey == pubkeys[validator_index]
|
assert state.validators[validator_index].pubkey == pubkeys[validator_index]
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
|
@ -203,7 +209,7 @@ def test_deposit_top_up(spec, state):
|
||||||
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
amount = spec.MAX_EFFECTIVE_BALANCE // 4
|
||||||
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
|
||||||
|
|
||||||
initial_registry_len = len(state.validator_registry)
|
initial_registry_len = len(state.validators)
|
||||||
initial_balances_len = len(state.balances)
|
initial_balances_len = len(state.balances)
|
||||||
validator_pre_balance = get_balance(state, validator_index)
|
validator_pre_balance = get_balance(state, validator_index)
|
||||||
|
|
||||||
|
@ -213,12 +219,12 @@ def test_deposit_top_up(spec, state):
|
||||||
block.body.deposits.append(deposit)
|
block.body.deposits.append(deposit)
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
|
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
spec.state_transition(state, block)
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert len(state.validator_registry) == initial_registry_len
|
assert len(state.validators) == initial_registry_len
|
||||||
assert len(state.balances) == initial_balances_len
|
assert len(state.balances) == initial_balances_len
|
||||||
assert get_balance(state, validator_index) == validator_pre_balance + amount
|
assert get_balance(state, validator_index) == validator_pre_balance + amount
|
||||||
|
|
||||||
|
@ -238,7 +244,7 @@ def test_attestation(spec, state):
|
||||||
attestation_block.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
attestation_block.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
attestation_block.body.attestations.append(attestation)
|
attestation_block.body.attestations.append(attestation)
|
||||||
sign_block(spec, state, attestation_block)
|
sign_block(spec, state, attestation_block)
|
||||||
spec.state_transition(state, attestation_block)
|
state_transition_and_sign_block(spec, state, attestation_block)
|
||||||
|
|
||||||
assert len(state.current_epoch_attestations) == pre_current_attestations_len + 1
|
assert len(state.current_epoch_attestations) == pre_current_attestations_len + 1
|
||||||
|
|
||||||
|
@ -248,7 +254,7 @@ def test_attestation(spec, state):
|
||||||
epoch_block = build_empty_block_for_next_slot(spec, state)
|
epoch_block = build_empty_block_for_next_slot(spec, state)
|
||||||
epoch_block.slot += spec.SLOTS_PER_EPOCH
|
epoch_block.slot += spec.SLOTS_PER_EPOCH
|
||||||
sign_block(spec, state, epoch_block)
|
sign_block(spec, state, epoch_block)
|
||||||
spec.state_transition(state, epoch_block)
|
state_transition_and_sign_block(spec, state, epoch_block)
|
||||||
|
|
||||||
yield 'blocks', [attestation_block, epoch_block], List[spec.BeaconBlock]
|
yield 'blocks', [attestation_block, epoch_block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
@ -287,20 +293,20 @@ def test_voluntary_exit(spec, state):
|
||||||
initiate_exit_block = build_empty_block_for_next_slot(spec, state)
|
initiate_exit_block = build_empty_block_for_next_slot(spec, state)
|
||||||
initiate_exit_block.body.voluntary_exits.append(voluntary_exit)
|
initiate_exit_block.body.voluntary_exits.append(voluntary_exit)
|
||||||
sign_block(spec, state, initiate_exit_block)
|
sign_block(spec, state, initiate_exit_block)
|
||||||
spec.state_transition(state, initiate_exit_block)
|
state_transition_and_sign_block(spec, state, initiate_exit_block)
|
||||||
|
|
||||||
assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
# Process within epoch transition
|
# Process within epoch transition
|
||||||
exit_block = build_empty_block_for_next_slot(spec, state)
|
exit_block = build_empty_block_for_next_slot(spec, state)
|
||||||
exit_block.slot += spec.SLOTS_PER_EPOCH
|
exit_block.slot += spec.SLOTS_PER_EPOCH
|
||||||
sign_block(spec, state, exit_block)
|
sign_block(spec, state, exit_block)
|
||||||
spec.state_transition(state, exit_block)
|
state_transition_and_sign_block(spec, state, exit_block)
|
||||||
|
|
||||||
yield 'blocks', [initiate_exit_block, exit_block], List[spec.BeaconBlock]
|
yield 'blocks', [initiate_exit_block, exit_block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
|
|
||||||
# @with_all_phases
|
# @with_all_phases
|
||||||
|
@ -317,7 +323,7 @@ def test_voluntary_exit(spec, state):
|
||||||
# pre_transfer_recipient_balance = get_balance(state, recipient_index)
|
# pre_transfer_recipient_balance = get_balance(state, recipient_index)
|
||||||
|
|
||||||
# un-activate so validator can transfer
|
# un-activate so validator can transfer
|
||||||
# state.validator_registry[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
# state.validators[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
# yield 'pre', state
|
# yield 'pre', state
|
||||||
|
|
||||||
|
@ -326,9 +332,9 @@ def test_voluntary_exit(spec, state):
|
||||||
# block.body.transfers.append(transfer)
|
# block.body.transfers.append(transfer)
|
||||||
# sign_block(spec, state, block)
|
# sign_block(spec, state, block)
|
||||||
|
|
||||||
# yield 'blocks', [block], List[spec.BeaconBlock]
|
# state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
# spec.state_transition(state, block)
|
# yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
# yield 'post', state
|
# yield 'post', state
|
||||||
|
|
||||||
# sender_balance = get_balance(state, sender_index)
|
# sender_balance = get_balance(state, sender_index)
|
||||||
|
@ -343,10 +349,10 @@ def test_balance_driven_status_transitions(spec, state):
|
||||||
current_epoch = spec.get_current_epoch(state)
|
current_epoch = spec.get_current_epoch(state)
|
||||||
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
|
||||||
|
|
||||||
assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
assert state.validators[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
# set validator balance to below ejection threshold
|
# set validator balance to below ejection threshold
|
||||||
state.validator_registry[validator_index].effective_balance = spec.EJECTION_BALANCE
|
state.validators[validator_index].effective_balance = spec.EJECTION_BALANCE
|
||||||
|
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
|
@ -354,12 +360,12 @@ def test_balance_driven_status_transitions(spec, state):
|
||||||
block = build_empty_block_for_next_slot(spec, state)
|
block = build_empty_block_for_next_slot(spec, state)
|
||||||
block.slot += spec.SLOTS_PER_EPOCH
|
block.slot += spec.SLOTS_PER_EPOCH
|
||||||
sign_block(spec, state, block)
|
sign_block(spec, state, block)
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
|
||||||
assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
|
||||||
|
|
||||||
|
|
||||||
@with_all_phases
|
@with_all_phases
|
||||||
|
@ -371,7 +377,7 @@ def test_historical_batch(spec, state):
|
||||||
yield 'pre', state
|
yield 'pre', state
|
||||||
|
|
||||||
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
block = build_empty_block_for_next_slot(spec, state, signed=True)
|
||||||
spec.state_transition(state, block)
|
state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
yield 'blocks', [block], List[spec.BeaconBlock]
|
yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
yield 'post', state
|
yield 'post', state
|
||||||
|
@ -392,7 +398,7 @@ def test_historical_batch(spec, state):
|
||||||
# blocks = []
|
# blocks = []
|
||||||
# for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1):
|
# for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1):
|
||||||
# block = build_empty_block_for_next_slot(spec, state)
|
# block = build_empty_block_for_next_slot(spec, state)
|
||||||
# spec.state_transition(state, block)
|
# state_transition_and_sign_block(spec, state, block)
|
||||||
# expected_votes += 1
|
# expected_votes += 1
|
||||||
# assert len(state.eth1_data_votes) == expected_votes
|
# assert len(state.eth1_data_votes) == expected_votes
|
||||||
# blocks.append(block)
|
# blocks.append(block)
|
||||||
|
@ -400,7 +406,7 @@ def test_historical_batch(spec, state):
|
||||||
# block = build_empty_block_for_next_slot(spec, state)
|
# block = build_empty_block_for_next_slot(spec, state)
|
||||||
# blocks.append(block)
|
# blocks.append(block)
|
||||||
|
|
||||||
# spec.state_transition(state, block)
|
# state_transition_and_sign_block(spec, state, block)
|
||||||
|
|
||||||
# yield 'blocks', [block], List[spec.BeaconBlock]
|
# yield 'blocks', [block], List[spec.BeaconBlock]
|
||||||
# yield 'post', state
|
# yield 'post', state
|
||||||
|
|
|
@ -2,7 +2,7 @@ from copy import deepcopy
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases
|
from eth2spec.test.context import spec_state_test, never_bls, with_all_phases
|
||||||
from eth2spec.test.helpers.state import next_epoch
|
from eth2spec.test.helpers.state import next_epoch, state_transition_and_sign_block
|
||||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, apply_empty_block
|
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, apply_empty_block
|
||||||
from eth2spec.test.helpers.attestations import get_valid_attestation
|
from eth2spec.test.helpers.attestations import get_valid_attestation
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ def next_epoch_with_attestations(spec,
|
||||||
prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest)
|
prev_attestation = get_valid_attestation(spec, post_state, slot_to_attest)
|
||||||
block.body.attestations.append(prev_attestation)
|
block.body.attestations.append(prev_attestation)
|
||||||
|
|
||||||
spec.state_transition(post_state, block)
|
state_transition_and_sign_block(spec, post_state, block)
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
|
||||||
return state, blocks, post_state
|
return state, blocks, post_state
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from types import GeneratorType
|
||||||
from typing import (
|
from typing import (
|
||||||
List,
|
List,
|
||||||
Iterable,
|
Iterable,
|
||||||
|
@ -362,6 +363,8 @@ def parse_bytes(val):
|
||||||
return val
|
return val
|
||||||
elif isinstance(val, int):
|
elif isinstance(val, int):
|
||||||
return bytes([val])
|
return bytes([val])
|
||||||
|
elif isinstance(val, (list, GeneratorType)):
|
||||||
|
return bytes(val)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
pytest>=3.6,<3.7
|
pytest>=3.6,<3.7
|
||||||
../config_helpers
|
../config_helpers
|
||||||
flake8==3.7.7
|
flake8==3.7.7
|
||||||
|
pytest-cov
|
||||||
|
|
|
@ -4,3 +4,4 @@ pycryptodome==3.7.3
|
||||||
py_ecc>=1.6.0
|
py_ecc>=1.6.0
|
||||||
typing_inspect==0.4.0
|
typing_inspect==0.4.0
|
||||||
dataclasses==0.6
|
dataclasses==0.6
|
||||||
|
ssz==0.1.0a10
|
||||||
|
|
|
@ -9,6 +9,7 @@ setup(
|
||||||
"eth-typing>=2.1.0,<3.0.0",
|
"eth-typing>=2.1.0,<3.0.0",
|
||||||
"pycryptodome==3.7.3",
|
"pycryptodome==3.7.3",
|
||||||
"py_ecc>=1.6.0",
|
"py_ecc>=1.6.0",
|
||||||
"typing_inspect==0.4.0"
|
"typing_inspect==0.4.0",
|
||||||
|
"ssz==0.1.0a10"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue