From a604d03dff66aed47a0790525651267008511fae Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Tue, 7 May 2019 12:13:22 +0100 Subject: [PATCH 01/55] Basic phase 1 pulling + correcting syntax errors in phase 1 --- Makefile | 10 +++++ scripts/phase0/build_spec.py | 37 +++++++++++++--- scripts/phase0/function_puller.py | 19 ++++++-- specs/core/1_custody-game.md | 19 +++++--- specs/core/1_shard-data-chains.md | 44 +++++++++---------- .../pyspec/eth2spec/utils/minimal_ssz.py | 4 ++ 6 files changed, 97 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index 73d8adea8..420fc3276 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ YAML_TEST_TARGETS = $(patsubst $(GENERATOR_DIR)/%, $(YAML_TEST_DIR)/%, $(GENERAT GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENERATORS)) PY_SPEC_PHASE_0_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase0/spec.py +PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/custody-game.py $(PY_SPEC_DIR)/eth2spec/phase1/shard-data-chains.py PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) @@ -25,6 +26,7 @@ clean: rm -rf $(GENERATOR_VENVS) rm -rf $(PY_SPEC_DIR)/venv $(PY_SPEC_DIR)/.pytest_cache rm -rf $(PY_SPEC_ALL_TARGETS) + rm -rf $(PY_SPEC_PHASE_1_TARGETS) # "make gen_yaml_tests" to run generators gen_yaml_tests: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_TARGETS) @@ -45,10 +47,18 @@ pyspec: $(PY_SPEC_ALL_TARGETS) # "make phase0" to create pyspec for phase0 phase0: $(PY_SPEC_PHASE_0_TARGETS) +# "make phase1" to create pyspec for phase1 +phase1: $(PY_SPEC_PHASE_1_TARGETS) $(PY_SPEC_DIR)/eth2spec/phase0/spec.py: python3 $(SCRIPT_DIR)/phase0/build_spec.py $(SPEC_DIR)/core/0_beacon-chain.md $@ +$(PY_SPEC_DIR)/eth2spec/phase1/custody-game.py: + python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_custody-game.md $@ + +$(PY_SPEC_DIR)/eth2spec/phase1/shard-data-chains.py: + python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_shard-data-chains.md $@ + CURRENT_DIR = ${CURDIR} diff --git a/scripts/phase0/build_spec.py b/scripts/phase0/build_spec.py index da5845951..80b378fbb 100644 --- a/scripts/phase0/build_spec.py +++ b/scripts/phase0/build_spec.py @@ -1,6 +1,6 @@ import sys import function_puller - +from optparse import OptionParser def build_phase0_spec(sourcefile, outfile): code_lines = [] @@ -85,8 +85,35 @@ def apply_constants_preset(preset: Dict[str, Any]): out.write("\n".join(code_lines)) -if __name__ == '__main__': - if len(sys.argv) < 3: - print("Usage: ") - build_phase0_spec(sys.argv[1], sys.argv[2]) +def build_phase1_spec(sourcefile, outfile): + code_lines = [] + code_lines.append(""" +from eth2spec.phase0.spec import * + +""") + + code_lines += function_puller.get_spec(sourcefile) + + with open(outfile, 'w') as out: + out.write("\n".join(code_lines)) + + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option("-p", "--phase", dest="phase", type="int", default=0, + help="Build for phase #") + + (options, args) = parser.parse_args() + + if len(args) < 2: + parser.print_help() + + if options.phase == 0: + build_phase0_spec(args[0], args[1]) + print(args[0]) + print(args[1]) + elif options.phase == 1: + build_phase1_spec(args[0], args[1]) + else: + print("Invalid phase: {0}".format(options["phase"])) diff --git a/scripts/phase0/function_puller.py b/scripts/phase0/function_puller.py index 1fad41fa9..393f821d5 100644 --- a/scripts/phase0/function_puller.py +++ b/scripts/phase0/function_puller.py @@ -2,16 +2,26 @@ import sys from typing import List -def get_spec(file_name: str) -> List[str]: +def get_spec(file_name: str, phase:int = 0) -> List[str]: code_lines = [] pulling_from = None current_name = None current_typedef = None + is_update_section = False + update_section_depth = None type_defs = [] - for linenum, line in enumerate(open(sys.argv[1]).readlines()): + for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': current_name = line[line[:-1].rfind('`') + 1: -1] + if pulling_from is None and len(line) > 0 and line[0] == '#' and line.endswith('updates'): + is_update_section = True + update_section_depth = max(i for i in range(10) if line.startswith('#' * i)) + elif pulling_from is None and len(line) > 0 and line[0] == '#' and is_update_section: + section_depth = max(i for i in range(10) if line.startswith('#' * i)) + if section_depth <= update_section_depth: + is_update_section = False + update_section_depth = None if line[:9] == '```python': assert pulling_from is None pulling_from = linenum + 1 @@ -28,7 +38,10 @@ def get_spec(file_name: str) -> List[str]: current_typedef = None else: if pulling_from == linenum and line == '{': - code_lines.append('%s = SSZType({' % current_name) + if is_update_section: + code_lines.append('%s = SSZTypeExtension({' % current_name) + else: + code_lines.append('%s = SSZType({' % current_name) current_typedef = ['global_vars["%s"] = SSZType({' % current_name] elif pulling_from is not None: # Add some whitespace between functions diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index d56526611..09e876ec3 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -220,16 +220,19 @@ Add the following fields to the end of the specified container objects. Fields w #### `Validator` ```python +{ # next_custody_reveal_period is initialised to the custody period # (of the particular validator) in which the validator is activated # = get_validators_custody_reveal_period(...) 'next_custody_reveal_period': 'uint64', 'max_reveal_lateness': 'uint64', +} ``` #### `BeaconState` ```python +{ 'custody_chunk_challenge_records': [CustodyChunkChallengeRecord], 'custody_bit_challenge_records': [CustodyBitChallengeRecord], 'custody_challenge_index': 'uint64', @@ -237,16 +240,19 @@ Add the following fields to the end of the specified container objects. Fields w # Future derived secrets already exposed; contains the indices of the exposed validator # at RANDAO reveal period % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS 'exposed_derived_secrets': [['uint64'], EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS], +} ``` #### `BeaconBlockBody` ```python +{ 'custody_chunk_challenges': [CustodyChunkChallenge], 'custody_bit_challenges': [CustodyBitChallenge], 'custody_responses': [CustodyResponse], 'custody_key_reveals': [CustodyKeyReveal], 'early_derived_secret_reveals': [EarlyDerivedSecretReveal], +} ``` ## Helpers @@ -299,7 +305,7 @@ def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorI ### `get_validators_custody_reveal_period` - ```python +```python def get_validators_custody_reveal_period(state: BeaconState, validator_index: ValidatorIndex, epoch: Epoch=None) -> int: @@ -484,7 +490,7 @@ def process_chunk_challenge(state: BeaconState, new_record = CustodyChunkChallengeRecord( challenge_index=state.custody_challenge_index, challenger_index=get_beacon_proposer_index(state), - responder_index=challenge.responder_index + responder_index=challenge.responder_index, deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, crosslink_data_root=challenge.attestation.data.crosslink_data_root, depth=depth, @@ -538,7 +544,7 @@ def process_bit_challenge(state: BeaconState, get_validators_custody_reveal_period( state=state, index=challenge.responder_index, - epoch=slot_to_epoch(attestation.data.slot), + epoch=slot_to_epoch(attestation.data.slot)), challenge.responder_index ) assert bls_verify( @@ -585,11 +591,11 @@ For each `response` in `block.body.custody_responses`, run the following functio ```python def process_custody_response(state: BeaconState, response: CustodyResponse) -> None: - chunk_challenge = next(record for record in state.custody_chunk_challenge_records if record.challenge_index == response.challenge_index, None) + chunk_challenge = next((record for record in state.custody_chunk_challenge_records if record.challenge_index == response.challenge_index), None) if chunk_challenge is not None: return process_chunk_challenge_response(state, response, chunk_challenge) - bit_challenge = next(record for record in state.custody_bit_challenge_records if record.challenge_index == response.challenge_index, None) + bit_challenge = next((record for record in state.custody_bit_challenge_records if record.challenge_index == response.challenge_index), None) if bit_challenge is not None: return process_bit_challenge_response(state, response, bit_challenge) @@ -657,7 +663,7 @@ def process_bit_challenge_response(state: BeaconState, Run `process_reveal_deadlines(state)` immediately after `process_ejections(state)`: - ```python +```python def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): if (validator.latest_custody_reveal_period + @@ -686,6 +692,7 @@ def process_challenge_deadlines(state: BeaconState) -> None: Append this to `process_final_updates(state)`: ```python +def after_process_final_updates(state: BeaconState) -> None: # Clean up exposed RANDAO key reveals state.exposed_derived_secrets[current_epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS] = [] ``` diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 33ef8632b..ffb7926f8 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -53,8 +53,8 @@ This document describes the shard data layer and the shard fork choice rule in P | Name | Value | Unit | Duration | | - | - | :-: | :-: | -| `CROSSLINK_LOOKBACK` | 2**0 (= 1) | epochs | 6.2 minutes | -| `PERSISTENT_COMMITTEE_PERIOD` | 2**11 (= 2,048) | epochs | ~9 days | +| `CROSSLINK_LOOKBACK` | `2**0` (= 1) | epochs | 6.2 minutes | +| `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days | ### Signature domains @@ -198,14 +198,14 @@ def get_shard_proposer_index(state: BeaconState, ```python def get_shard_header(block: ShardBlock) -> ShardBlockHeader: return ShardBlockHeader( - slot: block.slot, - shard: block.shard, - beacon_chain_root: block.beacon_chain_root, - previous_block_root: block.previous_block_root, - body_root: hash_tree_root(block.body), - state_root: block.state_root, - attestations: block.attestations, - signature: block.signature, + slot=block.slot, + shard=block.shard, + beacon_chain_root=block.beacon_chain_root, + previous_block_root=block.previous_block_root, + body_root=hash_tree_root(block.body), + state_root=block.state_root, + attestations=block.attestations, + signature=block.signature, ) ``` @@ -219,7 +219,7 @@ def verify_shard_attestation_signature(state: BeaconState, assert verify_bitfield(attestation.aggregation_bitfield, len(persistent_committee)) pubkeys = [] 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] assert is_active_validator(validator, get_current_epoch(state)) pubkeys.append(validator.pubkey) @@ -273,7 +273,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], beacon_state: BeaconState, valid_shard_blocks: List[ShardBlock], unix_time: uint64, - candidate: ShardBlock) -> bool + candidate: ShardBlock) -> bool: # Check if block is already determined valid for _, block in enumerate(valid_shard_blocks): if candidate == block: @@ -289,7 +289,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], # Check beacon block beacon_block = beacon_blocks[block.slot] assert block.beacon_block_root == signing_root(beacon_block) - assert beacon_block.slot <= block.slot: + assert beacon_block.slot <= block.slot # Check state root assert block.state_root == ZERO_HASH # [to be removed in phase 2] @@ -299,9 +299,9 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], assert candidate.previous_block_root == ZERO_HASH else: parent_block = next( - block for block in valid_shard_blocks if - signing_root(block) == candidate.previous_block_root - , None) + (block for block in valid_shard_blocks if + signing_root(block) == candidate.previous_block_root), + None) assert parent_block != None assert parent_block.shard == block.shard assert parent_block.slot < block.slot @@ -342,9 +342,9 @@ def is_valid_shard_attestation(valid_shard_blocks: List[ShardBlock], candidate: Attestation) -> bool: # Check shard block shard_block = next( - block for block in valid_shard_blocks if - signing_root(block) == candidate.attestation.data.shard_block_root - , None) + (block for block in valid_shard_blocks if + signing_root(block) == candidate.attestation.data.shard_block_root), + None) assert shard_block != None assert shard_block.slot == attestation.data.slot assert shard_block.shard == attestation.data.shard @@ -381,9 +381,9 @@ def is_valid_beacon_attestation(shard: Shard, assert candidate.data.previous_crosslink.crosslink_data_root == ZERO_HASH else: previous_attestation = next( - attestation for attestation in valid_attestations if - attestation.data.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root - , None) + (attestation for attestation in valid_attestations if + attestation.data.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root), + None) assert previous_attestation != None assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot) diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index 9cc2baebb..cfd2e56ac 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -37,6 +37,10 @@ def SSZType(fields): SSZObject.fields = fields return SSZObject +def SSZTypeExtension(original_type, new_fields): + fields = original_type.fields.copy() + fields.update(original_type.fields) + return SSZType(fields) class Vector(): def __init__(self, items): From 4ad92a0989bec522b5ccdf2d7969a76bfeaac715 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Tue, 7 May 2019 13:23:28 +0100 Subject: [PATCH 02/55] Fix typing --- scripts/phase0/function_puller.py | 2 +- specs/core/1_custody-game.md | 16 +++++----- specs/core/1_shard-data-chains.md | 52 ++++++++++++++++--------------- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/scripts/phase0/function_puller.py b/scripts/phase0/function_puller.py index 393f821d5..830e52a32 100644 --- a/scripts/phase0/function_puller.py +++ b/scripts/phase0/function_puller.py @@ -39,7 +39,7 @@ def get_spec(file_name: str, phase:int = 0) -> List[str]: else: if pulling_from == linenum and line == '{': if is_update_section: - code_lines.append('%s = SSZTypeExtension({' % current_name) + code_lines.append('%s = SSZTypeExtension(%s, {' % (current_name, current_name)) else: code_lines.append('%s = SSZType({' % current_name) current_typedef = ['global_vars["%s"] = SSZType({' % current_name] diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index c510abf6c..5de52a4ea 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -134,7 +134,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'attestation': Attestation, 'challenger_index': ValidatorIndex, 'responder_key': BLSSignature, - 'chunk_bits': Bitfield, + 'chunk_bits': "bytes", 'signature': BLSSignature, } ``` @@ -147,7 +147,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'challenger_index': ValidatorIndex, 'responder_index': ValidatorIndex, 'deadline': Epoch, - 'crosslink_data_root': Hash, + 'crosslink_data_root': 'bytes32', 'depth': 'uint64', 'chunk_index': 'uint64', } @@ -161,9 +161,9 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'challenger_index': ValidatorIndex, 'responder_index': ValidatorIndex, 'deadline': Epoch, - 'crosslink_data_root': Hash, + 'crosslink_data_root': 'bytes32', 'chunk_count': 'uint64', - 'chunk_bits_merkle_root': Hash, + 'chunk_bits_merkle_root': 'bytes32', 'responder_key': BLSSignature, } ``` @@ -175,9 +175,9 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'challenge_index': 'uint64', 'chunk_index': 'uint64', 'chunk': ['byte', BYTES_PER_CUSTODY_CHUNK], - 'data_branch': [Hash], - 'chunk_bits_branch': [Hash], - 'chunk_bits_leaf': Hash, + 'data_branch': ['bytes32'], + 'chunk_bits_branch': ['bytes32'], + 'chunk_bits_leaf': 'bytes32', } ``` @@ -287,7 +287,7 @@ def get_custody_chunk_bit(key: BLSSignature, chunk: bytes) -> bool: ### `get_chunk_bits_root` ```python -def get_chunk_bits_root(chunk_bitfield: Bitfield) -> Bytes32: +def get_chunk_bits_root(chunk_bitfield: bytes) -> Bytes32: aggregated_bits = bytearray([0] * 32) for i in range(0, len(chunk_bitfield), 32): for j in range(32): diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index c277dbdc3..691e38c04 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -15,9 +15,9 @@ - [Signature domains](#signature-domains) - [Data structures](#data-structures) - [`ShardBlockBody`](#shardblockbody) + - [`ShardAttestation`](#shardattestation) - [`ShardBlock`](#shardblock) - [`ShardBlockHeader`](#shardblockheader) - - [`ShardAttestation`](#shardattestation) - [Helper functions](#helper-functions) - [`get_period_committee`](#get_period_committee) - [`get_switchover_epoch`](#get_switchover_epoch) @@ -68,7 +68,23 @@ This document describes the shard data layer and the shard fork choice rule in P ### `ShardBlockBody` ```python -['byte', BYTES_PER_SHARD_BLOCK_BODY] +{ + 'data': ['byte', BYTES_PER_SHARD_BLOCK_BODY], +} +``` + +### `ShardAttestation` + +```python +{ + 'data': { + 'slot': Slot, + 'shard': Shard, + 'shard_block_root': 'bytes32', + }, + 'aggregation_bitfield': 'bytes', + 'aggregate_signature': BLSSignature, +} ``` ### `ShardBlock` @@ -77,10 +93,10 @@ This document describes the shard data layer and the shard fork choice rule in P { 'slot': Slot, 'shard': Shard, - 'beacon_chain_root': Hash, - 'previous_block_root': Hash, + 'beacon_chain_root': 'bytes32', + 'previous_block_root': 'bytes32', 'data': ShardBlockBody, - 'state_root': Hash, + 'state_root': 'bytes32', 'attestations': [ShardAttestation], 'signature': BLSSignature, } @@ -92,29 +108,15 @@ This document describes the shard data layer and the shard fork choice rule in P { 'slot': Slot, 'shard': Shard, - 'beacon_chain_root': Hash, - 'previous_block_root': Hash, - 'body_root': Hash, - 'state_root': Hash, + 'beacon_chain_root': 'bytes32', + 'previous_block_root': 'bytes32', + 'body_root': 'bytes32', + 'state_root': 'bytes32', 'attestations': [ShardAttestation], 'signature': BLSSignature, } ``` -### `ShardAttestation` - -```python -{ - 'data': { - 'slot': Slot, - 'shard': Shard, - 'shard_block_root': Hash, - }, - 'aggregation_bitfield': Bitfield, - 'aggregate_signature': BLSSignature, -} -``` - ## Helper functions ### `get_period_committee` @@ -234,7 +236,7 @@ def verify_shard_attestation_signature(state: BeaconState, ### `compute_crosslink_data_root` ```python -def compute_crosslink_data_root(blocks: List[ShardBlock]) -> Hash: +def compute_crosslink_data_root(blocks: List[ShardBlock]) -> 'bytes32': def is_power_of_two(value: int) -> bool: return (value > 0) and (value & (value - 1) == 0) @@ -272,7 +274,7 @@ Let: def is_valid_shard_block(beacon_blocks: List[BeaconBlock], beacon_state: BeaconState, valid_shard_blocks: List[ShardBlock], - unix_time: uint64, + unix_time: int, candidate: ShardBlock) -> bool: # Check if block is already determined valid for _, block in enumerate(valid_shard_blocks): From 79c193ff60e6941781bc3de57de74265633edb52 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Tue, 7 May 2019 18:07:51 +0100 Subject: [PATCH 03/55] Underscores for python modules --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 420fc3276..1c7f84ec6 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ YAML_TEST_TARGETS = $(patsubst $(GENERATOR_DIR)/%, $(YAML_TEST_DIR)/%, $(GENERAT GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENERATORS)) PY_SPEC_PHASE_0_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase0/spec.py -PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/custody-game.py $(PY_SPEC_DIR)/eth2spec/phase1/shard-data-chains.py +PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py $(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) @@ -53,10 +53,10 @@ phase1: $(PY_SPEC_PHASE_1_TARGETS) $(PY_SPEC_DIR)/eth2spec/phase0/spec.py: python3 $(SCRIPT_DIR)/phase0/build_spec.py $(SPEC_DIR)/core/0_beacon-chain.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/custody-game.py: +$(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py: python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_custody-game.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/shard-data-chains.py: +$(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py: python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_shard-data-chains.md $@ From 6ab55efd3d31fa0b5711a2f6843a70346a3e7704 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Wed, 8 May 2019 23:30:08 +0100 Subject: [PATCH 04/55] Phase 0 tests work on phase 1, yay :) --- Makefile | 10 ++- scripts/phase0/build_spec.py | 18 +++++ scripts/phase0/function_puller.py | 7 +- specs/core/1_custody-game.md | 5 +- test_libs/pyspec/eth2spec/phase1/__init__.py | 0 .../eth2spec/phase1/state_transition.py | 77 +++++++++++++++++++ .../pyspec/eth2spec/utils/minimal_ssz.py | 24 ++++-- .../test_process_attestation.py | 6 +- .../test_process_attester_slashing.py | 4 +- .../test_process_block_header.py | 2 +- .../block_processing/test_process_deposit.py | 4 +- .../test_process_proposer_slashing.py | 4 +- .../block_processing/test_process_transfer.py | 4 +- .../block_processing/test_voluntary_exit.py | 4 +- test_libs/pyspec/tests/conftest.py | 3 +- .../test_process_crosslinks.py | 6 +- .../test_process_registry_updates.py | 4 +- test_libs/pyspec/tests/helpers.py | 9 ++- test_libs/pyspec/tests/test_finality.py | 4 +- test_libs/pyspec/tests/test_sanity.py | 8 +- 20 files changed, 159 insertions(+), 44 deletions(-) create mode 100644 test_libs/pyspec/eth2spec/phase1/__init__.py create mode 100644 test_libs/pyspec/eth2spec/phase1/state_transition.py diff --git a/Makefile b/Makefile index 1c7f84ec6..65c8bc33d 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,11 @@ YAML_TEST_TARGETS = $(patsubst $(GENERATOR_DIR)/%, $(YAML_TEST_DIR)/%, $(GENERAT GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENERATORS)) PY_SPEC_PHASE_0_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase0/spec.py +PY_SPEC_PHASE_0_DEPS = $(SPEC_DIR)/core/0_*.md + PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py $(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py +PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md + PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) @@ -50,13 +54,13 @@ phase0: $(PY_SPEC_PHASE_0_TARGETS) # "make phase1" to create pyspec for phase1 phase1: $(PY_SPEC_PHASE_1_TARGETS) -$(PY_SPEC_DIR)/eth2spec/phase0/spec.py: +$(PY_SPEC_DIR)/eth2spec/phase0/spec.py: $(PY_SPEC_PHASE_0_DEPS) python3 $(SCRIPT_DIR)/phase0/build_spec.py $(SPEC_DIR)/core/0_beacon-chain.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py: +$(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py: $(PY_SPEC_PHASE_1_DEPS) python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_custody-game.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py: +$(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py: $(PY_SPEC_PHASE_0_DEPS) python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_shard-data-chains.md $@ diff --git a/scripts/phase0/build_spec.py b/scripts/phase0/build_spec.py index 80b378fbb..e3009004f 100644 --- a/scripts/phase0/build_spec.py +++ b/scripts/phase0/build_spec.py @@ -89,11 +89,29 @@ def build_phase1_spec(sourcefile, outfile): code_lines = [] code_lines.append(""" from eth2spec.phase0.spec import * +from eth2spec.phase0.spec import apply_constants_preset as apply_constants_preset_phase0 """) code_lines += function_puller.get_spec(sourcefile) + code_lines.append(""" +# Access to overwrite spec constants based on configuration +def apply_constants_preset(preset: Dict[str, Any]): + + apply_constants_preset_phase0(preset) + + global_vars = globals() + for k, v in preset.items(): + global_vars[k] = v + + # Deal with derived constants + global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) + + # Initialize SSZ types again, to account for changed lengths + init_SSZ_types() +""") + with open(outfile, 'w') as out: out.write("\n".join(code_lines)) diff --git a/scripts/phase0/function_puller.py b/scripts/phase0/function_puller.py index 830e52a32..26ac2f17f 100644 --- a/scripts/phase0/function_puller.py +++ b/scripts/phase0/function_puller.py @@ -39,10 +39,11 @@ def get_spec(file_name: str, phase:int = 0) -> List[str]: else: if pulling_from == linenum and line == '{': if is_update_section: - code_lines.append('%s = SSZTypeExtension(%s, {' % (current_name, current_name)) + code_lines.append('%s = SSZTypeExtension("%s", {' % (current_name, current_name)) + current_typedef = ['global_vars["%s"] = SSZTypeExtension("%s", {' % (current_name, current_name)] else: - code_lines.append('%s = SSZType({' % current_name) - current_typedef = ['global_vars["%s"] = SSZType({' % current_name] + code_lines.append('%s = SSZType("%s", {' % (current_name, current_name)) + current_typedef = ['global_vars["%s"] = SSZType("%s", {' % (current_name, current_name)] elif pulling_from is not None: # Add some whitespace between functions if line[:3] == 'def': diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 5de52a4ea..501bfce46 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -661,12 +661,12 @@ def process_bit_challenge_response(state: BeaconState, ### Handling of custody-related deadlines -Run `process_reveal_deadlines(state)` immediately after `process_ejections(state)`: +Run `process_reveal_deadlines(state)` immediately after `process_registry_updates(state)`: ```python def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): - if (validator.latest_custody_reveal_period + + if (validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) < get_validators_custody_reveal_period(state, index)): slash_validator(state, index) @@ -693,6 +693,7 @@ Append this to `process_final_updates(state)`: ```python def after_process_final_updates(state: BeaconState) -> None: + current_epoch = get_current_epoch(state) # Clean up exposed RANDAO key reveals state.exposed_derived_secrets[current_epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS] = [] ``` diff --git a/test_libs/pyspec/eth2spec/phase1/__init__.py b/test_libs/pyspec/eth2spec/phase1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/eth2spec/phase1/state_transition.py b/test_libs/pyspec/eth2spec/phase1/state_transition.py new file mode 100644 index 000000000..7e6411287 --- /dev/null +++ b/test_libs/pyspec/eth2spec/phase1/state_transition.py @@ -0,0 +1,77 @@ +from . import spec + +from typing import ( + Any, + Callable, + List +) + +from .spec import ( + BeaconState, + BeaconBlock, + Slot, +) + +from eth2spec.phase0.state_transition import ( + expected_deposit_count, + process_operation_type, + process_operations as process_operations_phase0, + process_block as process_block_phase0, + process_epoch_transition as process_epoch_transition_phase0, + state_transition_to as state_transition_to_phase0, + state_transition as state_transition_phase0 +) + +def process_operations(state: BeaconState, block: BeaconBlock) -> None: + process_operations_phase0(state, block) + + process_operation_type( + state, + block.body.custody_key_reveals, + spec.MAX_CUSTODY_KEY_REVEALS, + spec.process_custody_key_reveal, + ) + + process_operation_type( + state, + block.body.early_derived_secret_reveals, + spec.MAX_EARLY_DERIVED_SECRET_REVEALS, + spec.process_early_derived_secret_reveal, + ) + +def process_block(state: BeaconState, + block: BeaconBlock, + verify_state_root: bool=False) -> None: + spec.process_block_header(state, block) + spec.process_randao(state, block) + spec.process_eth1_data(state, block) + + process_operations(state, block) + if verify_state_root: + spec.verify_block_state_root(state, block) + +def process_epoch_transition(state: BeaconState) -> None: + spec.process_justification_and_finalization(state) + spec.process_crosslinks(state) + # TODO: Eligible + spec.process_rewards_and_penalties(state) + spec.process_registry_updates(state) + spec.process_reveal_deadlines(state) + spec.process_challenge_deadlines(state) + spec.process_slashings(state) + spec.process_final_updates(state) + spec.after_process_final_updates(state) + +def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState: + while state.slot < up_to: + spec.cache_state(state) + if (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0: + process_epoch_transition(state) + spec.advance_slot(state) + + +def state_transition(state: BeaconState, + block: BeaconBlock, + verify_state_root: bool=False) -> BeaconState: + state_transition_to(state, block.slot) + process_block(state, block, verify_state_root) \ No newline at end of file diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index cfd2e56ac..8a210f41b 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -6,9 +6,14 @@ BYTES_PER_CHUNK = 32 BYTES_PER_LENGTH_OFFSET = 4 ZERO_CHUNK = b'\x00' * BYTES_PER_CHUNK +cached_typedefs = {} -def SSZType(fields): +def SSZType(name, fields): class SSZObject(): + if name != None: + __name__ = name + __qualname__ = name + def __init__(self, **kwargs): for f, t in fields.items(): if f not in kwargs: @@ -25,8 +30,11 @@ def SSZType(fields): def __str__(self): output = [] for field in self.fields: - output.append(f'{field}: {getattr(self, field)}') + output.append(f'{field}: {repr(getattr(self, field))},') return "\n".join(output) + + def __repr__(self): + return name + "(**{\n " + str(self).replace("\n", "\n ") + "\n})" def serialize(self): return serialize_value(self, self.__class__) @@ -35,12 +43,16 @@ def SSZType(fields): return hash_tree_root(self, self.__class__) SSZObject.fields = fields + + if name != None: + cached_typedefs[name] = SSZObject + return SSZObject def SSZTypeExtension(original_type, new_fields): - fields = original_type.fields.copy() - fields.update(original_type.fields) - return SSZType(fields) + typedef = cached_typedefs[original_type] + typedef.fields.update(new_fields) + return typedef class Vector(): def __init__(self, items): @@ -319,7 +331,7 @@ def truncate(container): key: container.fields[key] for key in field_keys[:-1] } - truncated_class = SSZType(truncated_fields) + truncated_class = SSZType(None, truncated_fields) kwargs = { field: getattr(container, field) for field in field_keys[:-1] diff --git a/test_libs/pyspec/tests/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/block_processing/test_process_attestation.py index bcf71376c..18706c9e5 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/block_processing/test_process_attestation.py @@ -1,12 +1,12 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.state_transition import ( +from eth2spec.phase1.state_transition import ( state_transition, ) -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( get_current_epoch, process_attestation, slot_to_epoch, diff --git a/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py index 2ea16f13d..880ca829a 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py @@ -1,8 +1,8 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec -from eth2spec.phase0.spec import ( +import eth2spec.phase1.spec as spec +from eth2spec.phase1.spec import ( get_beacon_proposer_index, process_attester_slashing, ) diff --git a/test_libs/pyspec/tests/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/block_processing/test_process_block_header.py index b35b0a9c1..bcaf3c6d8 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/block_processing/test_process_block_header.py @@ -2,7 +2,7 @@ from copy import deepcopy import pytest -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( get_beacon_proposer_index, cache_state, advance_slot, diff --git a/test_libs/pyspec/tests/block_processing/test_process_deposit.py b/test_libs/pyspec/tests/block_processing/test_process_deposit.py index bbfb390ef..768f61678 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/tests/block_processing/test_process_deposit.py @@ -1,9 +1,9 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( ZERO_HASH, process_deposit, ) diff --git a/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py index 475221036..513e607b1 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py @@ -1,8 +1,8 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec -from eth2spec.phase0.spec import ( +import eth2spec.phase1.spec as spec +from eth2spec.phase1.spec import ( get_current_epoch, process_proposer_slashing, ) diff --git a/test_libs/pyspec/tests/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/block_processing/test_process_transfer.py index 0eeaa7792..02f448fd0 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/block_processing/test_process_transfer.py @@ -1,9 +1,9 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( get_active_validator_indices, get_beacon_proposer_index, get_current_epoch, diff --git a/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py b/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py index c58c5238a..c789b55d8 100644 --- a/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py +++ b/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py @@ -1,9 +1,9 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( get_active_validator_indices, get_churn_limit, get_current_epoch, diff --git a/test_libs/pyspec/tests/conftest.py b/test_libs/pyspec/tests/conftest.py index 9840dc7b2..98b64c73b 100644 --- a/test_libs/pyspec/tests/conftest.py +++ b/test_libs/pyspec/tests/conftest.py @@ -1,6 +1,6 @@ import pytest -from eth2spec.phase0 import spec +from eth2spec.phase1 import spec from preset_loader import loader from .helpers import ( @@ -20,7 +20,6 @@ def config(request): presets = loader.load_presets('../../configs/', config_name) spec.apply_constants_preset(presets) - @pytest.fixture def num_validators(config): return spec.SLOTS_PER_EPOCH * 8 diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py index d6765e3a7..9a6254715 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py @@ -1,12 +1,12 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.state_transition import ( +from eth2spec.phase1.state_transition import ( state_transition, ) -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( cache_state, get_crosslink_deltas, process_crosslinks, diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py index 11f5de2ad..15f7ae6ec 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py @@ -2,9 +2,9 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( get_current_epoch, is_active_validator, ) diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/helpers.py index 3b9b6904d..3156a7f28 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/helpers.py @@ -2,12 +2,12 @@ from copy import deepcopy from py_ecc import bls -from eth2spec.phase0.state_transition import ( +from eth2spec.phase1.state_transition import ( state_transition, ) -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( # constants ZERO_HASH, # SSZ @@ -420,3 +420,6 @@ def get_state_root(state, slot) -> bytes: """ assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT return state.latest_state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT] + +# Stub to be overwritten by config +import_spec = None \ No newline at end of file diff --git a/test_libs/pyspec/tests/test_finality.py b/test_libs/pyspec/tests/test_finality.py index ca048c2b2..46f08cfbb 100644 --- a/test_libs/pyspec/tests/test_finality.py +++ b/test_libs/pyspec/tests/test_finality.py @@ -2,9 +2,9 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec -from eth2spec.phase0.state_transition import ( +from eth2spec.phase1.state_transition import ( state_transition, ) from .helpers import ( diff --git a/test_libs/pyspec/tests/test_sanity.py b/test_libs/pyspec/tests/test_sanity.py index 1b4d20f4c..ea488fd1f 100644 --- a/test_libs/pyspec/tests/test_sanity.py +++ b/test_libs/pyspec/tests/test_sanity.py @@ -3,10 +3,10 @@ from copy import deepcopy import pytest from py_ecc import bls -import eth2spec.phase0.spec as spec +import eth2spec.phase1.spec as spec from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( # constants ZERO_HASH, SLOTS_PER_HISTORICAL_ROOT, @@ -25,7 +25,7 @@ from eth2spec.phase0.spec import ( verify_merkle_branch, hash, ) -from eth2spec.phase0.state_transition import ( +from eth2spec.phase1.state_transition import ( state_transition, ) from eth2spec.utils.merkle_minimal import ( @@ -326,7 +326,7 @@ def test_voluntary_exit(state): def test_transfer(state): # overwrite default 0 to test - spec.MAX_TRANSFERS = 1 + spec.apply_constants_preset({"MAX_TRANSFERS": 1}) pre_state = deepcopy(state) current_epoch = get_current_epoch(pre_state) From 909158ed2d26964615c5f2e9d45b0a62632643a5 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Wed, 8 May 2019 23:41:44 +0100 Subject: [PATCH 05/55] Correct makefile --- Makefile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 65c8bc33d..c48b81b68 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ GENERATOR_VENVS = $(patsubst $(GENERATOR_DIR)/%, $(GENERATOR_DIR)/%venv, $(GENER PY_SPEC_PHASE_0_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase0/spec.py PY_SPEC_PHASE_0_DEPS = $(SPEC_DIR)/core/0_*.md -PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py $(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py +PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/spec.py PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) @@ -46,7 +46,7 @@ citest: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; python -m pytest --junitxml=test-reports/eth2spec/test_results.xml . # "make pyspec" to create the pyspec for all phases. -pyspec: $(PY_SPEC_ALL_TARGETS) +pyspec: $(PY_SPEC_ALL_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) # "make phase0" to create pyspec for phase0 phase0: $(PY_SPEC_PHASE_0_TARGETS) @@ -57,13 +57,9 @@ phase1: $(PY_SPEC_PHASE_1_TARGETS) $(PY_SPEC_DIR)/eth2spec/phase0/spec.py: $(PY_SPEC_PHASE_0_DEPS) python3 $(SCRIPT_DIR)/phase0/build_spec.py $(SPEC_DIR)/core/0_beacon-chain.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/custody_game.py: $(PY_SPEC_PHASE_1_DEPS) +$(PY_SPEC_DIR)/eth2spec/phase1/spec.py: $(PY_SPEC_PHASE_1_DEPS) python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_custody-game.md $@ -$(PY_SPEC_DIR)/eth2spec/phase1/shard_data_chains.py: $(PY_SPEC_PHASE_0_DEPS) - python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_shard-data-chains.md $@ - - CURRENT_DIR = ${CURDIR} # The function that builds a set of suite files, by calling a generator for the given type (param 1) From 3217938b6f611892ed3fa71a06daa5891c155216 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Wed, 8 May 2019 23:48:12 +0100 Subject: [PATCH 06/55] Re-add early derived secret reveal tests --- .../phase1_test_process_randao_key_reveal.py | 109 ------------------ ...est_process_early_derived_secret_reveal.py | 109 ++++++++++++++++++ test_libs/pyspec/tests/helpers_phase1.py | 14 ++- 3 files changed, 117 insertions(+), 115 deletions(-) delete mode 100644 test_libs/pyspec/tests/block_processing_phase1/phase1_test_process_randao_key_reveal.py create mode 100644 test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py diff --git a/test_libs/pyspec/tests/block_processing_phase1/phase1_test_process_randao_key_reveal.py b/test_libs/pyspec/tests/block_processing_phase1/phase1_test_process_randao_key_reveal.py deleted file mode 100644 index 0be8ab4a9..000000000 --- a/test_libs/pyspec/tests/block_processing_phase1/phase1_test_process_randao_key_reveal.py +++ /dev/null @@ -1,109 +0,0 @@ -from copy import deepcopy -import pytest - -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - get_current_epoch, - process_randao_key_reveal, - RANDAO_PENALTY_EPOCHS, - CUSTODY_PERIOD_TO_RANDAO_PADDING, - RANDAO_PENALTY_MAX_FUTURE_EPOCHS, -) -from tests.helpers_phase1 import ( - get_valid_randao_key_reveal, -) - -mark entire file as 'randao_key_reveals' -pytestmark = pytest.mark.randao_key_reveals - - -def run_randao_key_reveal_processing(state, randao_key_reveal, valid=True): - """ - Run ``process_randao_key_reveal`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - process_randao_key_reveal(post_state, randao_key_reveal) - return state, None - - process_randao_key_reveal(post_state, randao_key_reveal) - - slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] - - if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - # FIXME: Currently broken because get_base_reward in genesis epoch is 0 - assert ( - post_state.balances[randao_key_reveal.revealed_index] < - state.balances[randao_key_reveal.revealed_index] - ) - - return state, post_state - - -def test_success(state): - randao_key_reveal = get_valid_randao_key_reveal(state) - - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal) - - return pre_state, randao_key_reveal, post_state - - -def test_reveal_from_current_epoch(state): - randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state)) - - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - -# Not currently possible as we are testing at epoch 0 -# -#def test_reveal_from_past_epoch(state): -# randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state) - 1) -# -# pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, False) -# -# return pre_state, randao_key_reveal, post_state - -def test_reveal_with_custody_padding(state): - randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - -def test_reveal_with_custody_padding_minus_one(state): - randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - -def test_double_reveal(state): - - randao_key_reveal1 = get_valid_randao_key_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) - pre_state, intermediate_state = run_randao_key_reveal_processing(state, randao_key_reveal1) - - randao_key_reveal2 = get_valid_randao_key_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) - intermediate_state_, post_state = run_randao_key_reveal_processing(intermediate_state, randao_key_reveal2, False) - - return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state - -def test_revealer_is_slashed(state): - randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state)) - state.validator_registry[randao_key_reveal.revealed_index].slashed = True - - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - -def test_far_future_epoch(state): - randao_key_reveal = get_valid_randao_key_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_MAX_FUTURE_EPOCHS) - - pre_state, post_state = run_randao_key_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py new file mode 100644 index 000000000..30ae1e77e --- /dev/null +++ b/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -0,0 +1,109 @@ +from copy import deepcopy +import pytest + +import eth2spec.phase1.spec as spec +from eth2spec.phase1.spec import ( + get_current_epoch, + process_early_derived_secret_reveal, + RANDAO_PENALTY_EPOCHS, + CUSTODY_PERIOD_TO_RANDAO_PADDING, + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, +) +from tests.helpers_phase1 import ( + get_valid_early_derived_secret_reveal, +) + +#mark entire file as 'randao_key_reveals' +pytestmark = pytest.mark.randao_key_reveals + + +def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): + """ + Run ``process_randao_key_reveal`` returning the pre and post state. + If ``valid == False``, run expecting ``AssertionError`` + """ + post_state = deepcopy(state) + + if not valid: + with pytest.raises(AssertionError): + process_early_derived_secret_reveal(post_state, randao_key_reveal) + return state, None + + process_early_derived_secret_reveal(post_state, randao_key_reveal) + + slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] + + if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: + assert slashed_validator.slashed + assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH + assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH + # lost whistleblower reward + # FIXME: Currently broken because get_base_reward in genesis epoch is 0 + assert ( + post_state.balances[randao_key_reveal.revealed_index] < + state.balances[randao_key_reveal.revealed_index] + ) + + return state, post_state + + +def test_success(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state) + + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) + + return pre_state, randao_key_reveal, post_state + + +def test_reveal_from_current_epoch(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) + + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + + return pre_state, randao_key_reveal, post_state + +# Not currently possible as we are testing at epoch 0 +# +#def test_reveal_from_past_epoch(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) +# +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) +# +# return pre_state, randao_key_reveal, post_state + +def test_reveal_with_custody_padding(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + + return pre_state, randao_key_reveal, post_state + +def test_reveal_with_custody_padding_minus_one(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + + return pre_state, randao_key_reveal, post_state + +def test_double_reveal(state): + + randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) + pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) + + randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) + intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + + return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + +def test_revealer_is_slashed(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) + state.validator_registry[randao_key_reveal.revealed_index].slashed = True + + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + + return pre_state, randao_key_reveal, post_state + +def test_far_future_epoch(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) + + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + + return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/helpers_phase1.py b/test_libs/pyspec/tests/helpers_phase1.py index aba93e159..5b67e9aa6 100644 --- a/test_libs/pyspec/tests/helpers_phase1.py +++ b/test_libs/pyspec/tests/helpers_phase1.py @@ -1,12 +1,12 @@ from py_ecc import bls import eth2spec.phase1.spec as spec -from eth2spec.phase0.spec import ( +from eth2spec.phase1.spec import ( # constants ZERO_HASH, CUSTODY_PERIOD_TO_RANDAO_PADDING, # SSZ - RandaoKeyReveal, + EarlyDerivedSecretReveal, # functions get_active_validator_indices, get_current_epoch, @@ -14,7 +14,9 @@ from eth2spec.phase0.spec import ( hash_tree_root, ) -def get_valid_randao_key_reveal(state, epoch=None): +from .helpers import privkeys + +def get_valid_early_derived_secret_reveal(state, epoch=None): current_epoch = get_current_epoch(state) revealed_index = get_active_validator_indices(state, current_epoch)[-1] masker_index = get_active_validator_indices(state, current_epoch)[0] @@ -24,7 +26,7 @@ def get_valid_randao_key_reveal(state, epoch=None): reveal = bls.sign( message_hash=hash_tree_root(epoch), - privkey=pubkey_to_privkey[state.validator_registry[revealed_index].pubkey], + privkey=privkeys[revealed_index], domain=get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, @@ -33,7 +35,7 @@ def get_valid_randao_key_reveal(state, epoch=None): ) mask = bls.sign( message_hash=hash_tree_root(epoch), - privkey=pubkey_to_privkey[state.validator_registry[masker_index].pubkey], + privkey=privkeys[masker_index], domain=get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, @@ -41,7 +43,7 @@ def get_valid_randao_key_reveal(state, epoch=None): ), ) - return RandaoKeyReveal( + return EarlyDerivedSecretReveal( revealed_index=revealed_index, epoch=epoch, reveal=reveal, From 838496c3d4945f619924166f0edd9d3b7de857b1 Mon Sep 17 00:00:00 2001 From: Dankrad Feist Date: Thu, 9 May 2019 00:42:59 +0100 Subject: [PATCH 07/55] Fix Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c48b81b68..5ca35c257 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ PY_SPEC_PHASE_0_DEPS = $(SPEC_DIR)/core/0_*.md PY_SPEC_PHASE_1_TARGETS = $(PY_SPEC_DIR)/eth2spec/phase1/spec.py PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md -PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) +PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) .PHONY: clean all test citest gen_yaml_tests pyspec phase0 install_test @@ -46,7 +46,7 @@ citest: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; python -m pytest --junitxml=test-reports/eth2spec/test_results.xml . # "make pyspec" to create the pyspec for all phases. -pyspec: $(PY_SPEC_ALL_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) +pyspec: $(PY_SPEC_ALL_TARGETS) # "make phase0" to create pyspec for phase0 phase0: $(PY_SPEC_PHASE_0_TARGETS) From f3742566f73e2d4d287e81193ac6d740ef8cded6 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 15 May 2019 15:02:27 +0200 Subject: [PATCH 08/55] The new test structure starts to take shape --- Makefile | 7 +- scripts/phase0/build_spec.py | 1 + test_libs/pyspec/__init__.py | 0 ...est_process_early_derived_secret_reveal.py | 109 ------------------ test_libs/pyspec/tests/phase0/__init__.py | 0 .../test_process_attestation.py | 9 +- .../test_process_attester_slashing.py | 6 +- .../test_process_block_header.py | 4 +- .../block_processing/test_process_deposit.py | 6 +- .../test_process_proposer_slashing.py | 6 +- .../block_processing/test_process_transfer.py | 6 +- .../block_processing/test_voluntary_exit.py | 6 +- .../pyspec/tests/{ => phase0}/conftest.py | 6 +- .../test_process_crosslinks.py | 11 +- .../test_process_registry_updates.py | 6 +- .../pyspec/tests/{ => phase0}/helpers.py | 10 +- .../tests/{ => phase0}/test_finality.py | 4 +- .../pyspec/tests/{ => phase0}/test_sanity.py | 7 +- test_libs/pyspec/tests/phase1/__init__.py | 0 ...est_process_early_derived_secret_reveal.py | 109 ++++++++++++++++++ test_libs/pyspec/tests/phase1/conftest.py | 9 ++ test_libs/pyspec/tests/phase1/helpers.py | 0 .../tests/{ => phase1}/helpers_phase1.py | 0 .../pyspec/tests/phase1/test_finality.py | 30 +++++ 24 files changed, 190 insertions(+), 162 deletions(-) create mode 100644 test_libs/pyspec/__init__.py delete mode 100644 test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py create mode 100644 test_libs/pyspec/tests/phase0/__init__.py rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_attestation.py (96%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_attester_slashing.py (97%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_block_header.py (96%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_deposit.py (97%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_proposer_slashing.py (96%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_process_transfer.py (97%) rename test_libs/pyspec/tests/{ => phase0}/block_processing/test_voluntary_exit.py (97%) rename test_libs/pyspec/tests/{ => phase0}/conftest.py (84%) rename test_libs/pyspec/tests/{ => phase0}/epoch_processing/test_process_crosslinks.py (95%) rename test_libs/pyspec/tests/{ => phase0}/epoch_processing/test_process_registry_updates.py (94%) rename test_libs/pyspec/tests/{ => phase0}/helpers.py (98%) rename test_libs/pyspec/tests/{ => phase0}/test_finality.py (98%) rename test_libs/pyspec/tests/{ => phase0}/test_sanity.py (99%) create mode 100644 test_libs/pyspec/tests/phase1/__init__.py create mode 100644 test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py create mode 100644 test_libs/pyspec/tests/phase1/conftest.py create mode 100644 test_libs/pyspec/tests/phase1/helpers.py rename test_libs/pyspec/tests/{ => phase1}/helpers_phase1.py (100%) create mode 100644 test_libs/pyspec/tests/phase1/test_finality.py diff --git a/Makefile b/Makefile index 4c4bfd88b..49460bdf1 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,6 @@ clean: rm -rf $(GENERATOR_VENVS) rm -rf $(PY_SPEC_DIR)/venv $(PY_SPEC_DIR)/.pytest_cache rm -rf $(PY_SPEC_ALL_TARGETS) - rm -rf $(PY_SPEC_PHASE_1_TARGETS) # "make gen_yaml_tests" to run generators gen_yaml_tests: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_TARGETS) @@ -42,6 +41,12 @@ install_test: test: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest . +test_phase0: $(PY_SPEC_ALL_TARGETS) + cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest tests/phase0 + +test_phase1: $(PY_SPEC_ALL_TARGETS) + cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest tests/phase1 + citest: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; python -m pytest --junitxml=test-reports/eth2spec/test_results.xml . diff --git a/scripts/phase0/build_spec.py b/scripts/phase0/build_spec.py index 0ebfd9906..4faf8cbf6 100644 --- a/scripts/phase0/build_spec.py +++ b/scripts/phase0/build_spec.py @@ -15,6 +15,7 @@ from typing import ( ) from eth2spec.utils.minimal_ssz import ( SSZType, + SSZTypeExtension, hash_tree_root, signing_root, ) diff --git a/test_libs/pyspec/__init__.py b/test_libs/pyspec/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py deleted file mode 100644 index 30ae1e77e..000000000 --- a/test_libs/pyspec/tests/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ /dev/null @@ -1,109 +0,0 @@ -from copy import deepcopy -import pytest - -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - get_current_epoch, - process_early_derived_secret_reveal, - RANDAO_PENALTY_EPOCHS, - CUSTODY_PERIOD_TO_RANDAO_PADDING, - EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, -) -from tests.helpers_phase1 import ( - get_valid_early_derived_secret_reveal, -) - -#mark entire file as 'randao_key_reveals' -pytestmark = pytest.mark.randao_key_reveals - - -def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): - """ - Run ``process_randao_key_reveal`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - process_early_derived_secret_reveal(post_state, randao_key_reveal) - return state, None - - process_early_derived_secret_reveal(post_state, randao_key_reveal) - - slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] - - if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - # FIXME: Currently broken because get_base_reward in genesis epoch is 0 - assert ( - post_state.balances[randao_key_reveal.revealed_index] < - state.balances[randao_key_reveal.revealed_index] - ) - - return state, post_state - - -def test_success(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) - - return pre_state, randao_key_reveal, post_state - - -def test_reveal_from_current_epoch(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - -# Not currently possible as we are testing at epoch 0 -# -#def test_reveal_from_past_epoch(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) -# -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# -# return pre_state, randao_key_reveal, post_state - -def test_reveal_with_custody_padding(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - -def test_reveal_with_custody_padding_minus_one(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - -def test_double_reveal(state): - - randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) - pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) - - randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) - intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) - - return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state - -def test_revealer_is_slashed(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) - state.validator_registry[randao_key_reveal.revealed_index].slashed = True - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - -def test_far_future_epoch(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase0/__init__.py b/test_libs/pyspec/tests/phase0/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/tests/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py similarity index 96% rename from test_libs/pyspec/tests/block_processing/test_process_attestation.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py index 0b1ceb79e..441df21e2 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py @@ -1,18 +1,15 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.state_transition import ( - state_transition, -) -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( get_current_epoch, process_attestation, slot_to_epoch, state_transition, ) -from tests.helpers import ( +from tests.phase0.helpers import ( build_empty_block_for_next_slot, get_valid_attestation, next_epoch, diff --git a/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py similarity index 97% rename from test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py index 880ca829a..d5e150b1d 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py @@ -1,12 +1,12 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( +import eth2spec.phase0.spec as spec +from eth2spec.phase0.spec import ( get_beacon_proposer_index, process_attester_slashing, ) -from tests.helpers import ( +from tests.phase0.helpers import ( get_balance, get_valid_attester_slashing, next_epoch, diff --git a/test_libs/pyspec/tests/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py similarity index 96% rename from test_libs/pyspec/tests/block_processing/test_process_block_header.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py index bb9deab28..4b66c2ff0 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py @@ -2,12 +2,12 @@ from copy import deepcopy import pytest -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( get_beacon_proposer_index, process_slot, process_block_header, ) -from tests.helpers import ( +from tests.phase0.helpers import ( advance_slot, build_empty_block_for_next_slot, next_slot, diff --git a/test_libs/pyspec/tests/block_processing/test_process_deposit.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py similarity index 97% rename from test_libs/pyspec/tests/block_processing/test_process_deposit.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py index 768f61678..0aa057c14 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py @@ -1,13 +1,13 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( ZERO_HASH, process_deposit, ) -from tests.helpers import ( +from tests.phase0.helpers import ( get_balance, build_deposit, privkeys, diff --git a/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py similarity index 96% rename from test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py index 513e607b1..366417d8b 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py @@ -1,12 +1,12 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( +import eth2spec.phase0.spec as spec +from eth2spec.phase0.spec import ( get_current_epoch, process_proposer_slashing, ) -from tests.helpers import ( +from tests.phase0.helpers import ( get_balance, get_valid_proposer_slashing, ) diff --git a/test_libs/pyspec/tests/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py similarity index 97% rename from test_libs/pyspec/tests/block_processing/test_process_transfer.py rename to test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py index 02f448fd0..cb657bb9d 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py @@ -1,15 +1,15 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( get_active_validator_indices, get_beacon_proposer_index, get_current_epoch, process_transfer, ) -from tests.helpers import ( +from tests.phase0.helpers import ( get_valid_transfer, next_epoch, ) diff --git a/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py similarity index 97% rename from test_libs/pyspec/tests/block_processing/test_voluntary_exit.py rename to test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py index c789b55d8..63be4c8f0 100644 --- a/test_libs/pyspec/tests/block_processing/test_voluntary_exit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py @@ -1,15 +1,15 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( get_active_validator_indices, get_churn_limit, get_current_epoch, process_voluntary_exit, ) -from tests.helpers import ( +from tests.phase0.helpers import ( build_voluntary_exit, pubkey_to_privkey, ) diff --git a/test_libs/pyspec/tests/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py similarity index 84% rename from test_libs/pyspec/tests/conftest.py rename to test_libs/pyspec/tests/phase0/conftest.py index 98b64c73b..4deb65da8 100644 --- a/test_libs/pyspec/tests/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -1,16 +1,16 @@ import pytest -from eth2spec.phase1 import spec +from eth2spec.phase0 import spec from preset_loader import loader -from .helpers import ( +from tests.phase0.helpers import ( create_genesis_state, ) def pytest_addoption(parser): parser.addoption( - "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" + "--config", action="store", default="minimal", help="config: make the p yspec use the specified configuration" ) diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py similarity index 95% rename from test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py rename to test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index b2202255f..6bd9b5d89 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -1,20 +1,15 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -<<<<<<< HEAD -from eth2spec.phase1.state_transition import ( - state_transition, -) -from eth2spec.phase1.spec import ( - cache_state, +from eth2spec.phase0.spec import ( process_slot, get_crosslink_deltas, process_crosslinks, state_transition, ) -from tests.helpers import ( +from tests.phase0.helpers import ( add_attestation_to_state, build_empty_block_for_next_slot, fill_aggregate_attestation, diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py similarity index 94% rename from test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py rename to test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py index 15f7ae6ec..54379de7d 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py @@ -2,13 +2,13 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( get_current_epoch, is_active_validator, ) -from tests.helpers import ( +from tests.phase0.helpers import ( next_epoch, ) diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py similarity index 98% rename from test_libs/pyspec/tests/helpers.py rename to test_libs/pyspec/tests/phase0/helpers.py index ed08013f1..e8b4f789e 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/phase0/helpers.py @@ -2,16 +2,10 @@ from copy import deepcopy from py_ecc import bls -<<<<<<< HEAD -from eth2spec.phase1.state_transition import ( - state_transition, -) -import eth2spec.phase1.spec as spec -======= import eth2spec.phase0.spec as spec ->>>>>>> dev + from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( # constants ZERO_HASH, MAX_EPOCHS_PER_CROSSLINK, diff --git a/test_libs/pyspec/tests/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py similarity index 98% rename from test_libs/pyspec/tests/test_finality.py rename to test_libs/pyspec/tests/phase0/test_finality.py index 20590154b..49569f220 100644 --- a/test_libs/pyspec/tests/test_finality.py +++ b/test_libs/pyspec/tests/phase0/test_finality.py @@ -2,9 +2,9 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec -from eth2spec.phase1.state_transition import ( +from eth2spec.phase0.spec import ( state_transition, ) diff --git a/test_libs/pyspec/tests/test_sanity.py b/test_libs/pyspec/tests/phase0/test_sanity.py similarity index 99% rename from test_libs/pyspec/tests/test_sanity.py rename to test_libs/pyspec/tests/phase0/test_sanity.py index 33a6f7221..7f3ee48e1 100644 --- a/test_libs/pyspec/tests/test_sanity.py +++ b/test_libs/pyspec/tests/phase0/test_sanity.py @@ -3,10 +3,10 @@ from copy import deepcopy import pytest from py_ecc import bls -import eth2spec.phase1.spec as spec +import eth2spec.phase0.spec as spec from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase1.spec import ( +from eth2spec.phase0.spec import ( # constants ZERO_HASH, SLOTS_PER_HISTORICAL_ROOT, @@ -22,9 +22,6 @@ from eth2spec.phase1.spec import ( get_domain, process_slot, verify_merkle_branch, - hash, -) -from eth2spec.phase1.state_transition import ( state_transition, hash, ) diff --git a/test_libs/pyspec/tests/phase1/__init__.py b/test_libs/pyspec/tests/phase1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py new file mode 100644 index 000000000..8c9bb0efb --- /dev/null +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -0,0 +1,109 @@ +# from copy import deepcopy +# import pytest + +# import eth2spec.phase1.spec as spec +# from eth2spec.phase1.spec import ( +# get_current_epoch, +# process_early_derived_secret_reveal, +# RANDAO_PENALTY_EPOCHS, +# CUSTODY_PERIOD_TO_RANDAO_PADDING, +# EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, +# ) +# from tests.helpers_phase1 import ( +# get_valid_early_derived_secret_reveal, +# ) + +# #mark entire file as 'randao_key_reveals' +# pytestmark = pytest.mark.randao_key_reveals + + +# def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): +# """ +# Run ``process_randao_key_reveal`` returning the pre and post state. +# If ``valid == False``, run expecting ``AssertionError`` +# """ +# post_state = deepcopy(state) + +# if not valid: +# with pytest.raises(AssertionError): +# process_early_derived_secret_reveal(post_state, randao_key_reveal) +# return state, None + +# process_early_derived_secret_reveal(post_state, randao_key_reveal) + +# slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] + +# if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: +# assert slashed_validator.slashed +# assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH +# assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH +# # lost whistleblower reward +# # FIXME: Currently broken because get_base_reward in genesis epoch is 0 +# assert ( +# post_state.balances[randao_key_reveal.revealed_index] < +# state.balances[randao_key_reveal.revealed_index] +# ) + +# return state, post_state + + +# def test_success(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state) + +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) + +# return pre_state, randao_key_reveal, post_state + + +# def test_reveal_from_current_epoch(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) + +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + +# return pre_state, randao_key_reveal, post_state + +# # Not currently possible as we are testing at epoch 0 +# # +# #def test_reveal_from_past_epoch(state): +# # randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) +# # +# # pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) +# # +# # return pre_state, randao_key_reveal, post_state + +# def test_reveal_with_custody_padding(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + +# return pre_state, randao_key_reveal, post_state + +# def test_reveal_with_custody_padding_minus_one(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + +# return pre_state, randao_key_reveal, post_state + +# def test_double_reveal(state): + +# randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) +# pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) + +# randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) +# intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + +# return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + +# def test_revealer_is_slashed(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) +# state.validator_registry[randao_key_reveal.revealed_index].slashed = True + +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + +# return pre_state, randao_key_reveal, post_state + +# def test_far_future_epoch(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) + +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + +# return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py new file mode 100644 index 000000000..4bacc1ea7 --- /dev/null +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -0,0 +1,9 @@ +import pytest + +from tests.phase0.conftest import ( + pytest_addoption, + config, + num_validators, + deposit_data_leaves, + state, +) diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/tests/helpers_phase1.py b/test_libs/pyspec/tests/phase1/helpers_phase1.py similarity index 100% rename from test_libs/pyspec/tests/helpers_phase1.py rename to test_libs/pyspec/tests/phase1/helpers_phase1.py diff --git a/test_libs/pyspec/tests/phase1/test_finality.py b/test_libs/pyspec/tests/phase1/test_finality.py new file mode 100644 index 000000000..b0acaa7cb --- /dev/null +++ b/test_libs/pyspec/tests/phase1/test_finality.py @@ -0,0 +1,30 @@ +from copy import deepcopy + +import pytest + +import eth2spec.phase1.spec as spec + +from eth2spec.phase1.spec import ( + state_transition, +) + +from tests.phase0.helpers import ( + build_empty_block_for_next_slot, + fill_aggregate_attestation, + get_current_epoch, + get_epoch_start_slot, + get_valid_attestation, + next_epoch, +) + +# mark entire file as 'state' +# pytestmark = pytest.mark.state + +from tests.phase0.test_finality import ( + pytestmark, + check_finality, + test_finality_rule_1, + test_finality_rule_2, + test_finality_rule_3, + test_finality_rule_4, +) From 77b29f4960b4b28790c754a5f389a24ea32e5d2e Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 15 May 2019 15:17:01 +0200 Subject: [PATCH 09/55] Early derived secret testing --- ...est_process_early_derived_secret_reveal.py | 167 +++++++++--------- test_libs/pyspec/tests/phase1/helpers.py | 54 ++++++ 2 files changed, 137 insertions(+), 84 deletions(-) diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index 8c9bb0efb..54a90aca1 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -1,109 +1,108 @@ -# from copy import deepcopy -# import pytest +from copy import deepcopy +import pytest -# import eth2spec.phase1.spec as spec -# from eth2spec.phase1.spec import ( -# get_current_epoch, -# process_early_derived_secret_reveal, -# RANDAO_PENALTY_EPOCHS, -# CUSTODY_PERIOD_TO_RANDAO_PADDING, -# EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, -# ) -# from tests.helpers_phase1 import ( -# get_valid_early_derived_secret_reveal, -# ) +import eth2spec.phase1.spec as spec +from eth2spec.phase1.spec import ( + get_current_epoch, + process_early_derived_secret_reveal, + RANDAO_PENALTY_EPOCHS, + CUSTODY_PERIOD_TO_RANDAO_PADDING, + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, +) +from tests.phase1.helpers import ( + get_valid_early_derived_secret_reveal, +) -# #mark entire file as 'randao_key_reveals' -# pytestmark = pytest.mark.randao_key_reveals +#mark entire file as 'randao_key_reveals' +pytestmark = pytest.mark.randao_key_reveals + +def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): + """ + Run ``process_randao_key_reveal`` returning the pre and post state. + If ``valid == False``, run expecting ``AssertionError`` + """ + post_state = deepcopy(state) + + if not valid: + with pytest.raises(AssertionError): + process_early_derived_secret_reveal(post_state, randao_key_reveal) + return state, None + + process_early_derived_secret_reveal(post_state, randao_key_reveal) + + slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] + + if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: + assert slashed_validator.slashed + assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH + assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH + # lost whistleblower reward + # FIXME: Currently broken because get_base_reward in genesis epoch is 0 + assert ( + post_state.balances[randao_key_reveal.revealed_index] < + state.balances[randao_key_reveal.revealed_index] + ) + + return state, post_state -# def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): -# """ -# Run ``process_randao_key_reveal`` returning the pre and post state. -# If ``valid == False``, run expecting ``AssertionError`` -# """ -# post_state = deepcopy(state) +def test_success(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state) -# if not valid: -# with pytest.raises(AssertionError): -# process_early_derived_secret_reveal(post_state, randao_key_reveal) -# return state, None + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) -# process_early_derived_secret_reveal(post_state, randao_key_reveal) - -# slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] - -# if randao_key_reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: -# assert slashed_validator.slashed -# assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH -# assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH -# # lost whistleblower reward -# # FIXME: Currently broken because get_base_reward in genesis epoch is 0 -# assert ( -# post_state.balances[randao_key_reveal.revealed_index] < -# state.balances[randao_key_reveal.revealed_index] -# ) - -# return state, post_state + return pre_state, randao_key_reveal, post_state -# def test_success(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state) +def test_reveal_from_current_epoch(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# return pre_state, randao_key_reveal, post_state + return pre_state, randao_key_reveal, post_state +# Not currently possible as we are testing at epoch 0 +# +#def test_reveal_from_past_epoch(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) +# +# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) +# +# return pre_state, randao_key_reveal, post_state -# def test_reveal_from_current_epoch(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) +def test_reveal_with_custody_padding(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + return pre_state, randao_key_reveal, post_state -# return pre_state, randao_key_reveal, post_state +def test_reveal_with_custody_padding_minus_one(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) -# # Not currently possible as we are testing at epoch 0 -# # -# #def test_reveal_from_past_epoch(state): -# # randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) -# # -# # pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# # -# # return pre_state, randao_key_reveal, post_state + return pre_state, randao_key_reveal, post_state -# def test_reveal_with_custody_padding(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - -# return pre_state, randao_key_reveal, post_state - -# def test_reveal_with_custody_padding_minus_one(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - -# return pre_state, randao_key_reveal, post_state - -# def test_double_reveal(state): +def test_double_reveal(state): -# randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) -# pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) + randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) + pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) -# randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) -# intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) + intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) -# return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state -# def test_revealer_is_slashed(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) -# state.validator_registry[randao_key_reveal.revealed_index].slashed = True +def test_revealer_is_slashed(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) + state.validator_registry[randao_key_reveal.revealed_index].slashed = True -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# return pre_state, randao_key_reveal, post_state + return pre_state, randao_key_reveal, post_state -# def test_far_future_epoch(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) +def test_far_future_epoch(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# return pre_state, randao_key_reveal, post_state + return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index e69de29bb..b12519b62 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -0,0 +1,54 @@ +from py_ecc import bls + +import eth2spec.phase1.spec as spec +from eth2spec.phase1.spec import ( + # constants + ZERO_HASH, + CUSTODY_PERIOD_TO_RANDAO_PADDING, + # SSZ + EarlyDerivedSecretReveal, + # functions + get_active_validator_indices, + get_current_epoch, + get_domain, + hash_tree_root, +) + +from tests.phase0.helpers import ( + privkeys, +) + +def get_valid_early_derived_secret_reveal(state, epoch=None): + current_epoch = get_current_epoch(state) + revealed_index = get_active_validator_indices(state, current_epoch)[-1] + masker_index = get_active_validator_indices(state, current_epoch)[0] + + if epoch is None: + epoch = current_epoch + CUSTODY_PERIOD_TO_RANDAO_PADDING + + reveal = bls.sign( + message_hash=hash_tree_root(epoch), + privkey=privkeys[revealed_index], + domain=get_domain( + state=state, + domain_type=spec.DOMAIN_RANDAO, + message_epoch=epoch, + ), + ) + mask = bls.sign( + message_hash=hash_tree_root(epoch), + privkey=privkeys[masker_index], + domain=get_domain( + state=state, + domain_type=spec.DOMAIN_RANDAO, + message_epoch=epoch, + ), + ) + + return EarlyDerivedSecretReveal( + revealed_index=revealed_index, + epoch=epoch, + reveal=reveal, + masker_index=masker_index, + mask=mask, + ) From becda4f463d6e7091ff95e6645afd44b2bc597dc Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 15 May 2019 16:26:49 +0200 Subject: [PATCH 10/55] Several changes before I break everything --- test_libs/pyspec/tests/phase0/conftest.py | 5 +- ...est_process_early_derived_secret_reveal.py | 18 ++--- test_libs/pyspec/tests/phase1/conftest.py | 21 +++++- test_libs/pyspec/tests/phase1/helpers.py | 11 +++ .../pyspec/tests/phase1/test_finality.py | 3 - test_libs/pyspec/tests/phase1/test_sanity.py | 68 +++++++++++++++++++ 6 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 test_libs/pyspec/tests/phase1/test_sanity.py diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index 4deb65da8..a3ea0a00c 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -10,10 +10,9 @@ from tests.phase0.helpers import ( def pytest_addoption(parser): parser.addoption( - "--config", action="store", default="minimal", help="config: make the p yspec use the specified configuration" + "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" ) - @pytest.fixture(autouse=True) def config(request): config_name = request.config.getoption("--config") @@ -24,12 +23,10 @@ def config(request): def num_validators(config): return spec.SLOTS_PER_EPOCH * 8 - @pytest.fixture def deposit_data_leaves(): return list() - @pytest.fixture def state(num_validators, deposit_data_leaves): return create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index 54a90aca1..6661e883f 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -61,14 +61,14 @@ def test_reveal_from_current_epoch(state): return pre_state, randao_key_reveal, post_state -# Not currently possible as we are testing at epoch 0 -# -#def test_reveal_from_past_epoch(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) -# -# pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) -# -# return pre_state, randao_key_reveal, post_state + +@pytest.mark.skip(reason="Not currently possible as we are testing at epoch 0") +def test_reveal_from_past_epoch(state): + randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) + + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + + return pre_state, randao_key_reveal, post_state def test_reveal_with_custody_padding(state): randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) @@ -88,7 +88,7 @@ def test_double_reveal(state): pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) - intermediate_state_, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + _, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 4bacc1ea7..c73f25c1b 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -1,9 +1,26 @@ import pytest +from eth2spec.phase1 import spec +from preset_loader import loader + +from tests.phase0.helpers import ( + create_genesis_state, +) + from tests.phase0.conftest import ( pytest_addoption, - config, num_validators, deposit_data_leaves, - state, ) + +# This is redfined so that the constants are re-applied +@pytest.fixture(autouse=True) +def config(request): + config_name = request.config.getoption("--config") + presets = loader.load_presets('../../configs/', config_name) + spec.apply_constants_preset(presets) + +#This is redefined so that the BeaconState is the new SSZ Object +@pytest.fixture +def state(num_validators, deposit_data_leaves): + return create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index b12519b62..8520ce9d7 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -15,7 +15,18 @@ from eth2spec.phase1.spec import ( ) from tests.phase0.helpers import ( + advance_slot, + get_balance, + build_deposit_data, + build_empty_block_for_next_slot, + fill_aggregate_attestation, + get_state_root, + get_valid_attestation, + get_valid_attester_slashing, + get_valid_proposer_slashing, + next_slot, privkeys, + pubkeys, ) def get_valid_early_derived_secret_reveal(state, epoch=None): diff --git a/test_libs/pyspec/tests/phase1/test_finality.py b/test_libs/pyspec/tests/phase1/test_finality.py index b0acaa7cb..4b57c9493 100644 --- a/test_libs/pyspec/tests/phase1/test_finality.py +++ b/test_libs/pyspec/tests/phase1/test_finality.py @@ -17,9 +17,6 @@ from tests.phase0.helpers import ( next_epoch, ) -# mark entire file as 'state' -# pytestmark = pytest.mark.state - from tests.phase0.test_finality import ( pytestmark, check_finality, diff --git a/test_libs/pyspec/tests/phase1/test_sanity.py b/test_libs/pyspec/tests/phase1/test_sanity.py new file mode 100644 index 000000000..45a08bd0e --- /dev/null +++ b/test_libs/pyspec/tests/phase1/test_sanity.py @@ -0,0 +1,68 @@ +from copy import deepcopy + +import pytest + +from py_ecc import bls +import eth2spec.phase1.spec as spec + +from eth2spec.utils.minimal_ssz import signing_root +from eth2spec.phase1.spec import ( + # constants + ZERO_HASH, + SLOTS_PER_HISTORICAL_ROOT, + # SSZ + Deposit, + Transfer, + VoluntaryExit, + # functions + get_active_validator_indices, + get_beacon_proposer_index, + get_block_root_at_slot, + get_current_epoch, + get_domain, + process_slot, + verify_merkle_branch, + state_transition, + hash, +) +from eth2spec.utils.merkle_minimal import ( + calc_merkle_tree_from_leaves, + get_merkle_proof, + get_merkle_root, +) +from .helpers import ( + advance_slot, + get_balance, + build_deposit_data, + build_empty_block_for_next_slot, + fill_aggregate_attestation, + get_state_root, + get_valid_attestation, + get_valid_attester_slashing, + get_valid_proposer_slashing, + next_slot, + privkeys, + pubkeys, +) + + +# mark entire file as 'sanity' +pytestmark = pytest.mark.sanity + +from tests.phase0.test_sanity import ( + test_slot_transition, + test_empty_block_transition, + test_skipped_slots, + test_empty_epoch_transition, + test_empty_epoch_transition_not_finalizing, + test_proposer_slashing, + test_attester_slashing, + test_deposit_in_block, + test_deposit_top_up, + test_attestation, + test_voluntary_exit, + test_transfer, + test_balance_driven_status_transitions, + test_historical_batch, + test_eth1_data_votes, +) From 1b2e7c1b6eab6a8b1b28e7fb87ed67b4c8d0a092 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 11:07:21 +0200 Subject: [PATCH 11/55] Passes spec & helpers module to tests phase0 --- .../test_process_attestation.py | 97 +++---- .../test_process_attester_slashing.py | 66 ++--- .../test_process_block_header.py | 55 ++-- .../block_processing/test_process_deposit.py | 69 ++--- .../test_process_proposer_slashing.py | 53 ++-- .../block_processing/test_process_transfer.py | 83 +++--- .../block_processing/test_voluntary_exit.py | 89 +++---- test_libs/pyspec/tests/phase0/conftest.py | 21 +- .../test_process_crosslinks.py | 89 +++---- .../test_process_registry_updates.py | 32 +-- .../pyspec/tests/phase0/test_finality.py | 69 ++--- test_libs/pyspec/tests/phase0/test_sanity.py | 239 ++++++++---------- 12 files changed, 404 insertions(+), 558 deletions(-) diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py index 441df21e2..5dcf17e38 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py @@ -1,41 +1,26 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - get_current_epoch, - process_attestation, - slot_to_epoch, - state_transition, -) -from tests.phase0.helpers import ( - build_empty_block_for_next_slot, - get_valid_attestation, - next_epoch, - next_slot, -) - # mark entire file as 'attestations' pytestmark = pytest.mark.attestations -def run_attestation_processing(state, attestation, valid=True): +def run_attestation_processing(spec, helpers, state, attestation, valid=True): """ - Run ``process_attestation`` returning the pre and post state. + Run ``spec.process_attestation`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_attestation(post_state, attestation) + spec.process_attestation(post_state, attestation) return state, None - process_attestation(post_state, attestation) + spec.process_attestation(post_state, attestation) - current_epoch = get_current_epoch(state) + current_epoch = spec.get_current_epoch(state) if attestation.data.target_epoch == current_epoch: assert len(post_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1 else: @@ -44,110 +29,110 @@ def run_attestation_processing(state, attestation, valid=True): return state, post_state -def test_success(state): - attestation = get_valid_attestation(state) +def test_success(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - pre_state, post_state = run_attestation_processing(state, attestation) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) return pre_state, attestation, post_state -def test_success_prevous_epoch(state): - attestation = get_valid_attestation(state) - block = build_empty_block_for_next_slot(state) +def test_success_prevous_epoch(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) + block = helpers.build_empty_block_for_next_slot(state) block.slot = state.slot + spec.SLOTS_PER_EPOCH - state_transition(state, block) + spec.state_transition(state, block) - pre_state, post_state = run_attestation_processing(state, attestation) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) return pre_state, attestation, post_state -def test_before_inclusion_delay(state): - attestation = get_valid_attestation(state) +def test_before_inclusion_delay(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) # do not increment slot to allow for inclusion delay - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_after_epoch_slots(state): - attestation = get_valid_attestation(state) - block = build_empty_block_for_next_slot(state) +def test_after_epoch_slots(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) + block = helpers.build_empty_block_for_next_slot(state) # increment past latest inclusion slot block.slot = state.slot + spec.SLOTS_PER_EPOCH + 1 - state_transition(state, block) + spec.state_transition(state, block) - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_bad_source_epoch(state): - attestation = get_valid_attestation(state) +def test_bad_source_epoch(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.source_epoch += 10 - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_bad_source_root(state): - attestation = get_valid_attestation(state) +def test_bad_source_root(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.source_root = b'\x42' * 32 - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_non_zero_crosslink_data_root(state): - attestation = get_valid_attestation(state) +def test_non_zero_crosslink_data_root(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.crosslink.data_root = b'\x42' * 32 - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_bad_previous_crosslink(state): - next_epoch(state) - attestation = get_valid_attestation(state) +def test_bad_previous_crosslink(spec, helpers, state): + helpers.next_epoch(state) + attestation = helpers.get_valid_attestation(state) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - next_slot(state) + helpers.next_slot(state) state.current_crosslinks[attestation.data.crosslink.shard].epoch += 10 - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_non_empty_custody_bitfield(state): - attestation = get_valid_attestation(state) +def test_non_empty_custody_bitfield(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) - pre_state, post_state = run_attestation_processing(state, attestation, False) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) return pre_state, attestation, post_state -def test_empty_aggregation_bitfield(state): - attestation = get_valid_attestation(state) +def test_empty_aggregation_bitfield(spec, helpers, state): + attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.aggregation_bitfield = b'\x00' * len(attestation.aggregation_bitfield) - pre_state, post_state = run_attestation_processing(state, attestation) + pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) return pre_state, attestation, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py index d5e150b1d..ed48b17cf 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py @@ -1,34 +1,24 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec -from eth2spec.phase0.spec import ( - get_beacon_proposer_index, - process_attester_slashing, -) -from tests.phase0.helpers import ( - get_balance, - get_valid_attester_slashing, - next_epoch, -) # mark entire file as 'attester_slashing' pytestmark = pytest.mark.attester_slashings -def run_attester_slashing_processing(state, attester_slashing, valid=True): +def run_attester_slashing_processing(spec, helpers, state, attester_slashing, valid=True): """ - Run ``process_attester_slashing`` returning the pre and post state. + Run ``spec.process_attester_slashing`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_attester_slashing(post_state, attester_slashing) + spec.process_attester_slashing(post_state, attester_slashing) return state, None - process_attester_slashing(post_state, attester_slashing) + spec.process_attester_slashing(post_state, attester_slashing) slashed_index = attester_slashing.attestation_1.custody_bit_0_indices[0] slashed_validator = post_state.validator_registry[slashed_index] @@ -37,63 +27,63 @@ def run_attester_slashing_processing(state, attester_slashing, valid=True): assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward assert ( - get_balance(post_state, slashed_index) < - get_balance(state, slashed_index) + helpers.get_balance(post_state, slashed_index) < + helpers.get_balance(state, slashed_index) ) - proposer_index = get_beacon_proposer_index(state) + proposer_index = spec.get_beacon_proposer_index(state) # gained whistleblower reward assert ( - get_balance(post_state, proposer_index) > - get_balance(state, proposer_index) + helpers.get_balance(post_state, proposer_index) > + helpers.get_balance(state, proposer_index) ) return state, post_state -def test_success_double(state): - attester_slashing = get_valid_attester_slashing(state) +def test_success_double(spec, helpers, state): + attester_slashing = helpers.get_valid_attester_slashing(state) - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing) return pre_state, attester_slashing, post_state -def test_success_surround(state): - next_epoch(state) +def test_success_surround(spec, helpers, state): + helpers.next_epoch(state) state.current_justified_epoch += 1 - attester_slashing = get_valid_attester_slashing(state) + attester_slashing = helpers.get_valid_attester_slashing(state) # set attestion1 to surround attestation 2 attester_slashing.attestation_1.data.source_epoch = attester_slashing.attestation_2.data.source_epoch - 1 attester_slashing.attestation_1.data.target_epoch = attester_slashing.attestation_2.data.target_epoch + 1 - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing) return pre_state, attester_slashing, post_state -def test_same_data(state): - attester_slashing = get_valid_attester_slashing(state) +def test_same_data(spec, helpers, state): + attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.data = attester_slashing.attestation_2.data - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_no_double_or_surround(state): - attester_slashing = get_valid_attester_slashing(state) +def test_no_double_or_surround(spec, helpers, state): + attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.data.target_epoch += 1 - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_participants_already_slashed(state): - attester_slashing = get_valid_attester_slashing(state) +def test_participants_already_slashed(spec, helpers, state): + attester_slashing = helpers.get_valid_attester_slashing(state) # set all indices to slashed attestation_1 = attester_slashing.attestation_1 @@ -101,17 +91,17 @@ def test_participants_already_slashed(state): for index in validator_indices: state.validator_registry[index].slashed = True - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_custody_bit_0_and_1(state): - attester_slashing = get_valid_attester_slashing(state) +def test_custody_bit_0_and_1(spec, helpers, state): + attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.custody_bit_1_indices = ( attester_slashing.attestation_1.custody_bit_0_indices ) - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) return pre_state, attester_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py index 4b66c2ff0..e4cd70f77 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py @@ -2,75 +2,64 @@ from copy import deepcopy import pytest -from eth2spec.phase0.spec import ( - get_beacon_proposer_index, - process_slot, - process_block_header, -) -from tests.phase0.helpers import ( - advance_slot, - build_empty_block_for_next_slot, - next_slot, -) - # mark entire file as 'header' pytestmark = pytest.mark.header -def prepare_state_for_header_processing(state): - process_slot(state) - advance_slot(state) +def prepare_state_for_header_processing(spec, helpers, state): + spec.process_slot(state) + helpers.advance_slot(state) -def run_block_header_processing(state, block, valid=True): +def run_block_header_processing(spec, helpers, state, block, valid=True): """ - Run ``process_block_header`` returning the pre and post state. + Run ``spec.process_block_header`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ - prepare_state_for_header_processing(state) + prepare_state_for_header_processing(spec, helpers, state) post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_block_header(post_state, block) + spec.process_block_header(post_state, block) return state, None - process_block_header(post_state, block) + spec.process_block_header(post_state, block) return state, post_state -def test_success(state): - block = build_empty_block_for_next_slot(state) - pre_state, post_state = run_block_header_processing(state, block) +def test_success(spec, helpers, state): + block = helpers.build_empty_block_for_next_slot(state) + pre_state, post_state = run_block_header_processing(spec, helpers, state, block) return state, block, post_state -def test_invalid_slot(state): - block = build_empty_block_for_next_slot(state) +def test_invalid_slot(spec, helpers, state): + block = helpers.build_empty_block_for_next_slot(state) block.slot = state.slot + 2 # invalid slot - pre_state, post_state = run_block_header_processing(state, block, valid=False) + pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) return pre_state, block, None -def test_invalid_parent_block_root(state): - block = build_empty_block_for_next_slot(state) +def test_invalid_parent_block_root(spec, helpers, state): + block = helpers.build_empty_block_for_next_slot(state) block.parent_root = b'\12' * 32 # invalid prev root - pre_state, post_state = run_block_header_processing(state, block, valid=False) + pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) return pre_state, block, None -def test_proposer_slashed(state): +def test_proposer_slashed(spec, helpers, state): # use stub state to get proposer index of next slot stub_state = deepcopy(state) - next_slot(stub_state) - proposer_index = get_beacon_proposer_index(stub_state) + helpers.next_slot(stub_state) + proposer_index = spec.get_beacon_proposer_index(stub_state) # set proposer to slashed state.validator_registry[proposer_index].slashed = True - block = build_empty_block_for_next_slot(state) + block = helpers.build_empty_block_for_next_slot(state) - pre_state, post_state = run_block_header_processing(state, block, valid=False) + pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) return pre_state, block, None diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py index 0aa057c14..97d49114b 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py @@ -1,33 +1,20 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - ZERO_HASH, - process_deposit, -) -from tests.phase0.helpers import ( - get_balance, - build_deposit, - privkeys, - pubkeys, -) - # mark entire file as 'deposits' pytestmark = pytest.mark.deposits -def test_success(state): +def test_success(spec, helpers, state): pre_state = deepcopy(state) # fill previous deposits with zero-hash - deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) index = len(deposit_data_leaves) - pubkey = pubkeys[index] - privkey = privkeys[index] - deposit, root, deposit_data_leaves = build_deposit( + pubkey = helpers.pubkeys[index] + privkey = helpers.privkeys[index] + deposit, root, deposit_data_leaves = helpers.build_deposit( pre_state, deposit_data_leaves, pubkey, @@ -40,26 +27,26 @@ def test_success(state): post_state = deepcopy(pre_state) - process_deposit(post_state, deposit) + spec.process_deposit(post_state, deposit) assert len(post_state.validator_registry) == len(state.validator_registry) + 1 assert len(post_state.balances) == len(state.balances) + 1 - assert post_state.validator_registry[index].pubkey == pubkeys[index] - assert get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE + assert post_state.validator_registry[index].pubkey == helpers.pubkeys[index] + assert helpers.get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count return pre_state, deposit, post_state -def test_success_top_up(state): +def test_success_top_up(spec, helpers, state): pre_state = deepcopy(state) - deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 - pubkey = pubkeys[validator_index] - privkey = privkeys[validator_index] - deposit, root, deposit_data_leaves = build_deposit( + pubkey = helpers.pubkeys[validator_index] + privkey = helpers.privkeys[validator_index] + deposit, root, deposit_data_leaves = helpers.build_deposit( pre_state, deposit_data_leaves, pubkey, @@ -69,28 +56,28 @@ def test_success_top_up(state): pre_state.latest_eth1_data.deposit_root = root pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves) - pre_balance = get_balance(pre_state, validator_index) + pre_balance = helpers.get_balance(pre_state, validator_index) post_state = deepcopy(pre_state) - process_deposit(post_state, deposit) + spec.process_deposit(post_state, deposit) assert len(post_state.validator_registry) == len(state.validator_registry) assert len(post_state.balances) == len(state.balances) assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count - assert get_balance(post_state, validator_index) == pre_balance + amount + assert helpers.get_balance(post_state, validator_index) == pre_balance + amount return pre_state, deposit, post_state -def test_wrong_index(state): +def test_wrong_index(spec, helpers, state): pre_state = deepcopy(state) - deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) index = len(deposit_data_leaves) - pubkey = pubkeys[index] - privkey = privkeys[index] - deposit, root, deposit_data_leaves = build_deposit( + pubkey = helpers.pubkeys[index] + privkey = helpers.privkeys[index] + deposit, root, deposit_data_leaves = helpers.build_deposit( pre_state, deposit_data_leaves, pubkey, @@ -107,19 +94,19 @@ def test_wrong_index(state): post_state = deepcopy(pre_state) with pytest.raises(AssertionError): - process_deposit(post_state, deposit) + spec.process_deposit(post_state, deposit) return pre_state, deposit, None -def test_bad_merkle_proof(state): +def test_bad_merkle_proof(spec, helpers, state): pre_state = deepcopy(state) - deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) index = len(deposit_data_leaves) - pubkey = pubkeys[index] - privkey = privkeys[index] - deposit, root, deposit_data_leaves = build_deposit( + pubkey = helpers.pubkeys[index] + privkey = helpers.privkeys[index] + deposit, root, deposit_data_leaves = helpers.build_deposit( pre_state, deposit_data_leaves, pubkey, @@ -136,6 +123,6 @@ def test_bad_merkle_proof(state): post_state = deepcopy(pre_state) with pytest.raises(AssertionError): - process_deposit(post_state, deposit) + spec.process_deposit(post_state, deposit) return pre_state, deposit, None diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py index 366417d8b..6f82d6c33 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py @@ -1,33 +1,24 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec -from eth2spec.phase0.spec import ( - get_current_epoch, - process_proposer_slashing, -) -from tests.phase0.helpers import ( - get_balance, - get_valid_proposer_slashing, -) # mark entire file as 'proposer_slashings' pytestmark = pytest.mark.proposer_slashings -def run_proposer_slashing_processing(state, proposer_slashing, valid=True): +def run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, valid=True): """ - Run ``process_proposer_slashing`` returning the pre and post state. + Run ``spec.process_proposer_slashing`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_proposer_slashing(post_state, proposer_slashing) + spec.process_proposer_slashing(post_state, proposer_slashing) return state, None - process_proposer_slashing(post_state, proposer_slashing) + spec.process_proposer_slashing(post_state, proposer_slashing) slashed_validator = post_state.validator_registry[proposer_slashing.proposer_index] assert slashed_validator.slashed @@ -35,62 +26,62 @@ def run_proposer_slashing_processing(state, proposer_slashing, valid=True): assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward assert ( - get_balance(post_state, proposer_slashing.proposer_index) < - get_balance(state, proposer_slashing.proposer_index) + helpers.get_balance(post_state, proposer_slashing.proposer_index) < + helpers.get_balance(state, proposer_slashing.proposer_index) ) return state, post_state -def test_success(state): - proposer_slashing = get_valid_proposer_slashing(state) +def test_success(spec, helpers, state): + proposer_slashing = helpers.get_valid_proposer_slashing(state) - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing) + pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing) return pre_state, proposer_slashing, post_state -def test_epochs_are_different(state): - proposer_slashing = get_valid_proposer_slashing(state) +def test_epochs_are_different(spec, helpers, state): + proposer_slashing = helpers.get_valid_proposer_slashing(state) # set slots to be in different epochs proposer_slashing.header_2.slot += spec.SLOTS_PER_EPOCH - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_headers_are_same(state): - proposer_slashing = get_valid_proposer_slashing(state) +def test_headers_are_same(spec, helpers, state): + proposer_slashing = helpers.get_valid_proposer_slashing(state) # set headers to be the same proposer_slashing.header_2 = proposer_slashing.header_1 - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_proposer_is_slashed(state): - proposer_slashing = get_valid_proposer_slashing(state) +def test_proposer_is_slashed(spec, helpers, state): + proposer_slashing = helpers.get_valid_proposer_slashing(state) # set proposer to slashed state.validator_registry[proposer_slashing.proposer_index].slashed = True - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_proposer_is_withdrawn(state): - proposer_slashing = get_valid_proposer_slashing(state) +def test_proposer_is_withdrawn(spec, helpers, state): + proposer_slashing = helpers.get_valid_proposer_slashing(state) # set proposer withdrawable_epoch in past - current_epoch = get_current_epoch(state) + current_epoch = spec.get_current_epoch(state) proposer_index = proposer_slashing.proposer_index state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1 - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) return pre_state, proposer_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py index cb657bb9d..197898ec0 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py @@ -1,40 +1,27 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - get_active_validator_indices, - get_beacon_proposer_index, - get_current_epoch, - process_transfer, -) -from tests.phase0.helpers import ( - get_valid_transfer, - next_epoch, -) - # mark entire file as 'transfers' pytestmark = pytest.mark.transfers -def run_transfer_processing(state, transfer, valid=True): +def run_transfer_processing(spec, helpers, state, transfer, valid=True): """ - Run ``process_transfer`` returning the pre and post state. + Run ``spec.process_transfer`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_transfer(post_state, transfer) + spec.process_transfer(post_state, transfer) return state, None - process_transfer(post_state, transfer) + spec.process_transfer(post_state, transfer) - proposer_index = get_beacon_proposer_index(state) + proposer_index = spec.get_beacon_proposer_index(state) pre_transfer_sender_balance = state.balances[transfer.sender] pre_transfer_recipient_balance = state.balances[transfer.recipient] pre_transfer_proposer_balance = state.balances[proposer_index] @@ -47,95 +34,95 @@ def run_transfer_processing(state, transfer, valid=True): return state, post_state -def test_success_non_activated(state): - transfer = get_valid_transfer(state) +def test_success_non_activated(spec, helpers, state): + transfer = helpers.get_valid_transfer(state) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(state, transfer) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) return pre_state, transfer, post_state -def test_success_withdrawable(state): - next_epoch(state) +def test_success_withdrawable(spec, helpers, state): + helpers.next_epoch(state) - transfer = get_valid_transfer(state) + transfer = helpers.get_valid_transfer(state) # withdrawable_epoch in past so can transfer - state.validator_registry[transfer.sender].withdrawable_epoch = get_current_epoch(state) - 1 + state.validator_registry[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1 - pre_state, post_state = run_transfer_processing(state, transfer) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) return pre_state, transfer, post_state -def test_success_active_above_max_effective(state): - sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1] +def test_success_active_above_max_effective(spec, helpers, state): + sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE // 32 state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + amount - transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) + transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - pre_state, post_state = run_transfer_processing(state, transfer) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) return pre_state, transfer, post_state -def test_active_but_transfer_past_effective_balance(state): - sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1] +def test_active_but_transfer_past_effective_balance(spec, helpers, state): + sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE // 32 state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE - transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) + transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - pre_state, post_state = run_transfer_processing(state, transfer, False) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) return pre_state, transfer, post_state -def test_incorrect_slot(state): - transfer = get_valid_transfer(state, slot=state.slot+1) +def test_incorrect_slot(spec, helpers, state): + transfer = helpers.get_valid_transfer(state, slot=state.slot+1) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(state, transfer, False) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) return pre_state, transfer, post_state -def test_insufficient_balance(state): - sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1] +def test_insufficient_balance(spec, helpers, state): + sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE - transfer = get_valid_transfer(state, sender_index=sender_index, amount=amount + 1, fee=0) + transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount + 1, fee=0) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(state, transfer, False) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) return pre_state, transfer, post_state -def test_no_dust(state): - sender_index = get_active_validator_indices(state, get_current_epoch(state))[-1] +def test_no_dust(spec, helpers, state): + sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] balance = state.balances[sender_index] - transfer = get_valid_transfer(state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, fee=0) + transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, fee=0) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(state, transfer, False) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) return pre_state, transfer, post_state -def test_invalid_pubkey(state): - transfer = get_valid_transfer(state) +def test_invalid_pubkey(spec, helpers, state): + transfer = helpers.get_valid_transfer(state) state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(state, transfer, False) + pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) return pre_state, transfer, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py index 63be4c8f0..d9e643b55 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py @@ -1,37 +1,24 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - get_active_validator_indices, - get_churn_limit, - get_current_epoch, - process_voluntary_exit, -) -from tests.phase0.helpers import ( - build_voluntary_exit, - pubkey_to_privkey, -) - # mark entire file as 'voluntary_exits' pytestmark = pytest.mark.voluntary_exits -def run_voluntary_exit_processing(state, voluntary_exit, valid=True): +def run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, valid=True): """ - Run ``process_voluntary_exit`` returning the pre and post state. + Run ``spec.process_voluntary_exit`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ post_state = deepcopy(state) if not valid: with pytest.raises(AssertionError): - process_voluntary_exit(post_state, voluntary_exit) + spec.process_voluntary_exit(post_state, voluntary_exit) return state, None - process_voluntary_exit(post_state, voluntary_exit) + spec.process_voluntary_exit(post_state, voluntary_exit) validator_index = voluntary_exit.validator_index assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH @@ -40,56 +27,56 @@ def run_voluntary_exit_processing(state, voluntary_exit, valid=True): return state, post_state -def test_success(state): +def test_success(spec, helpers, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[0] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - voluntary_exit = build_voluntary_exit( + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, validator_index, privkey, ) - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit) return pre_state, voluntary_exit, post_state -def test_success_exit_queue(state): +def test_success_exit_queue(spec, helpers, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - current_epoch = get_current_epoch(state) + current_epoch = spec.get_current_epoch(state) # exit `MAX_EXITS_PER_EPOCH` - initial_indices = get_active_validator_indices(state, current_epoch)[:get_churn_limit(state)] + initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_churn_limit(state)] post_state = state for index in initial_indices: - privkey = pubkey_to_privkey[state.validator_registry[index].pubkey] - voluntary_exit = build_voluntary_exit( + privkey = helpers.pubkey_to_privkey[state.validator_registry[index].pubkey] + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, index, privkey, ) - pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, post_state, voluntary_exit) # exit an additional validator - validator_index = get_active_validator_indices(state, current_epoch)[-1] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - voluntary_exit = build_voluntary_exit( + validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] + privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, validator_index, privkey, ) - pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, post_state, voluntary_exit) assert ( post_state.validator_registry[validator_index].exit_epoch == @@ -99,55 +86,55 @@ def test_success_exit_queue(state): return pre_state, voluntary_exit, post_state -def test_validator_not_active(state): - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[0] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] +def test_validator_not_active(spec, helpers, state): + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH # # build and test voluntary exit # - voluntary_exit = build_voluntary_exit( + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, validator_index, privkey, ) - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) return pre_state, voluntary_exit, post_state -def test_validator_already_exited(state): +def test_validator_already_exited(spec, helpers, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[0] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] # but validator already has exited state.validator_registry[validator_index].exit_epoch = current_epoch + 2 - voluntary_exit = build_voluntary_exit( + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, validator_index, privkey, ) - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) return pre_state, voluntary_exit, post_state -def test_validator_not_active_long_enough(state): - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[0] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] +def test_validator_not_active_long_enough(spec, helpers, state): + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[0] + privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - voluntary_exit = build_voluntary_exit( + voluntary_exit = helpers.build_voluntary_exit( state, current_epoch, validator_index, @@ -159,5 +146,5 @@ def test_validator_not_active_long_enough(state): spec.PERSISTENT_COMMITTEE_PERIOD ) - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) return pre_state, voluntary_exit, post_state diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index a3ea0a00c..25b540aa0 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -1,11 +1,9 @@ import pytest -from eth2spec.phase0 import spec +from eth2spec.phase0 import spec as _spec from preset_loader import loader -from tests.phase0.helpers import ( - create_genesis_state, -) +from tests.phase0 import helpers as _helpers def pytest_addoption(parser): @@ -17,11 +15,11 @@ def pytest_addoption(parser): def config(request): config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) - spec.apply_constants_preset(presets) + _spec.apply_constants_preset(presets) @pytest.fixture def num_validators(config): - return spec.SLOTS_PER_EPOCH * 8 + return _spec.SLOTS_PER_EPOCH * 8 @pytest.fixture def deposit_data_leaves(): @@ -29,4 +27,13 @@ def deposit_data_leaves(): @pytest.fixture def state(num_validators, deposit_data_leaves): - return create_genesis_state(num_validators, deposit_data_leaves) + return _helpers.create_genesis_state(num_validators, deposit_data_leaves) + +@pytest.fixture +def spec(): + return _spec + +@pytest.fixture +def helpers(): + return _helpers + diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index 6bd9b5d89..6e4ad2dd6 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -1,48 +1,29 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - process_slot, - get_crosslink_deltas, - process_crosslinks, - state_transition, -) -from tests.phase0.helpers import ( - add_attestation_to_state, - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_crosslink_committee, - get_valid_attestation, - next_epoch, - next_slot, - set_bitfield_bit, -) - # mark entire file as 'crosslinks' pytestmark = pytest.mark.crosslinks -def run_process_crosslinks(state, valid=True): +def run_process_crosslinks(spec, helpers, state, valid=True): # transition state to slot before state transition slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 - block = build_empty_block_for_next_slot(state) + block = helpers.build_empty_block_for_next_slot(state) block.slot = slot - state_transition(state, block) + spec.state_transition(state, block) # cache state before epoch transition - process_slot(state) + spec.process_slot(state) post_state = deepcopy(state) - process_crosslinks(post_state) + spec.process_crosslinks(post_state) return state, post_state -def test_no_attestations(state): - pre_state, post_state = run_process_crosslinks(state) +def test_no_attestations(spec, helpers, state): + pre_state, post_state = run_process_crosslinks(spec, helpers, state) for shard in range(spec.SHARD_COUNT): assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] @@ -50,17 +31,17 @@ def test_no_attestations(state): return pre_state, post_state -def test_single_crosslink_update_from_current_epoch(state): - next_epoch(state) +def test_single_crosslink_update_from_current_epoch(spec, helpers, state): + helpers.next_epoch(state) - attestation = get_valid_attestation(state) + attestation = helpers.get_valid_attestation(state) - fill_aggregate_attestation(state, attestation) - add_attestation_to_state(state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) + helpers.fill_aggregate_attestation(state, attestation) + helpers.add_attestation_to_state(state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) assert len(state.current_epoch_attestations) == 1 - pre_state, post_state = run_process_crosslinks(state) + pre_state, post_state = run_process_crosslinks(spec, helpers, state) shard = attestation.data.crosslink.shard assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] @@ -69,65 +50,65 @@ def test_single_crosslink_update_from_current_epoch(state): return pre_state, post_state -def test_single_crosslink_update_from_previous_epoch(state): - next_epoch(state) +def test_single_crosslink_update_from_previous_epoch(spec, helpers, state): + helpers.next_epoch(state) - attestation = get_valid_attestation(state) + attestation = helpers.get_valid_attestation(state) - fill_aggregate_attestation(state, attestation) - add_attestation_to_state(state, attestation, state.slot + spec.SLOTS_PER_EPOCH) + helpers.fill_aggregate_attestation(state, attestation) + helpers.add_attestation_to_state(state, attestation, state.slot + spec.SLOTS_PER_EPOCH) assert len(state.previous_epoch_attestations) == 1 - pre_state, post_state = run_process_crosslinks(state) - crosslink_deltas = get_crosslink_deltas(state) + pre_state, post_state = run_process_crosslinks(spec, helpers, state) + crosslink_deltas = spec.get_crosslink_deltas(state) shard = attestation.data.crosslink.shard assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard] # ensure rewarded - for index in get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): + for index in helpers.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[1][index] == 0 return pre_state, post_state -def test_double_late_crosslink(state): - next_epoch(state) +def test_double_late_crosslink(spec, helpers, state): + helpers.next_epoch(state) state.slot += 4 - attestation_1 = get_valid_attestation(state) - fill_aggregate_attestation(state, attestation_1) + attestation_1 = helpers.get_valid_attestation(state) + helpers.fill_aggregate_attestation(state, attestation_1) # add attestation_1 in the next epoch - next_epoch(state) - add_attestation_to_state(state, attestation_1, state.slot + 1) + helpers.next_epoch(state) + helpers.add_attestation_to_state(state, attestation_1, state.slot + 1) for slot in range(spec.SLOTS_PER_EPOCH): - attestation_2 = get_valid_attestation(state) + attestation_2 = helpers.get_valid_attestation(state) if attestation_2.data.crosslink.shard == attestation_1.data.crosslink.shard: break - next_slot(state) - fill_aggregate_attestation(state, attestation_2) + helpers.next_slot(state) + helpers.fill_aggregate_attestation(state, attestation_2) # add attestation_2 in the next epoch after attestation_1 has # already updated the relevant crosslink - next_epoch(state) - add_attestation_to_state(state, attestation_2, state.slot + 1) + helpers.next_epoch(state) + helpers.add_attestation_to_state(state, attestation_2, state.slot + 1) assert len(state.previous_epoch_attestations) == 1 assert len(state.current_epoch_attestations) == 0 - pre_state, post_state = run_process_crosslinks(state) - crosslink_deltas = get_crosslink_deltas(state) + pre_state, post_state = run_process_crosslinks(spec, helpers, state) + crosslink_deltas = spec.get_crosslink_deltas(state) shard = attestation_2.data.crosslink.shard # ensure that the current crosslinks were not updated by the second attestation assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink - for index in get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): + for index in helpers.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py index 54379de7d..8b5ebf9b4 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py @@ -1,51 +1,41 @@ from copy import deepcopy - import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - get_current_epoch, - is_active_validator, -) -from tests.phase0.helpers import ( - next_epoch, -) # mark entire file as 'state' pytestmark = pytest.mark.state -def test_activation(state): +def test_activation(spec, helpers, state): index = 0 - assert is_active_validator(state.validator_registry[index], get_current_epoch(state)) + assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) # Mock a new deposit state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE - assert not is_active_validator(state.validator_registry[index], get_current_epoch(state)) + assert not spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) pre_state = deepcopy(state) blocks = [] for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): - block = next_epoch(state) + block = helpers.next_epoch(state) blocks.append(block) assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH - assert is_active_validator( + assert spec.is_active_validator( state.validator_registry[index], - get_current_epoch(state), + spec.get_current_epoch(state), ) return pre_state, blocks, state -def test_ejection(state): +def test_ejection(spec, helpers, state): index = 0 - assert is_active_validator(state.validator_registry[index], get_current_epoch(state)) + assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH # Mock an ejection @@ -55,13 +45,13 @@ def test_ejection(state): blocks = [] for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): - block = next_epoch(state) + block = helpers.next_epoch(state) blocks.append(block) assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH - assert not is_active_validator( + assert not spec.is_active_validator( state.validator_registry[index], - get_current_epoch(state), + spec.get_current_epoch(state), ) return pre_state, blocks, state diff --git a/test_libs/pyspec/tests/phase0/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py index 49569f220..e30e125f9 100644 --- a/test_libs/pyspec/tests/phase0/test_finality.py +++ b/test_libs/pyspec/tests/phase0/test_finality.py @@ -2,21 +2,6 @@ from copy import deepcopy import pytest -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - state_transition, -) - -from .helpers import ( - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_current_epoch, - get_epoch_start_slot, - get_valid_attestation, - next_epoch, -) - # mark entire file as 'state' pytestmark = pytest.mark.state @@ -48,24 +33,24 @@ def check_finality(state, assert state.finalized_root == prev_state.finalized_root -def next_epoch_with_attestations(state, +def next_epoch_with_attestations(spec, helpers, state, fill_cur_epoch, fill_prev_epoch): post_state = deepcopy(state) blocks = [] for _ in range(spec.SLOTS_PER_EPOCH): - block = build_empty_block_for_next_slot(post_state) + block = helpers.build_empty_block_for_next_slot(post_state) if fill_cur_epoch: slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 - if slot_to_attest >= get_epoch_start_slot(get_current_epoch(post_state)): - cur_attestation = get_valid_attestation(post_state, slot_to_attest) - fill_aggregate_attestation(post_state, cur_attestation) + if slot_to_attest >= helpers.get_epoch_start_slot(helpers.get_current_epoch(post_state)): + cur_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) + helpers.fill_aggregate_attestation(post_state, cur_attestation) block.body.attestations.append(cur_attestation) if fill_prev_epoch: slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 - prev_attestation = get_valid_attestation(post_state, slot_to_attest) - fill_aggregate_attestation(post_state, prev_attestation) + prev_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) + helpers.fill_aggregate_attestation(post_state, prev_attestation) block.body.attestations.append(prev_attestation) spec.state_transition(post_state, block) @@ -74,12 +59,12 @@ def next_epoch_with_attestations(state, return state, blocks, post_state -def test_finality_rule_4(state): +def test_finality_rule_4(spec, helpers, state): test_state = deepcopy(state) blocks = [] for epoch in range(4): - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) blocks += new_blocks # justification/finalization skipped at GENESIS_EPOCH @@ -99,17 +84,17 @@ def test_finality_rule_4(state): return state, blocks, test_state -def test_finality_rule_1(state): +def test_finality_rule_1(spec, helpers, state): # get past first two epochs that finality does not run on - next_epoch(state) - next_epoch(state) + helpers.next_epoch(state) + helpers.next_epoch(state) pre_state = deepcopy(state) test_state = deepcopy(state) blocks = [] for epoch in range(3): - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) blocks += new_blocks if epoch == 0: @@ -125,10 +110,10 @@ def test_finality_rule_1(state): return pre_state, blocks, test_state -def test_finality_rule_2(state): +def test_finality_rule_2(spec, helpers, state): # get past first two epochs that finality does not run on - next_epoch(state) - next_epoch(state) + helpers.next_epoch(state) + helpers.next_epoch(state) pre_state = deepcopy(state) test_state = deepcopy(state) @@ -136,13 +121,13 @@ def test_finality_rule_2(state): blocks = [] for epoch in range(3): if epoch == 0: - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) check_finality(test_state, prev_state, True, False, False) elif epoch == 1: - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, False) check_finality(test_state, prev_state, False, True, False) elif epoch == 2: - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) # finalized by rule 2 check_finality(test_state, prev_state, True, False, True) assert test_state.finalized_epoch == prev_state.previous_justified_epoch @@ -153,43 +138,43 @@ def test_finality_rule_2(state): return pre_state, blocks, test_state -def test_finality_rule_3(state): +def test_finality_rule_3(spec, helpers, state): """ Test scenario described here https://github.com/ethereum/eth2.0-specs/issues/611#issuecomment-463612892 """ # get past first two epochs that finality does not run on - next_epoch(state) - next_epoch(state) + helpers.next_epoch(state) + helpers.next_epoch(state) pre_state = deepcopy(state) test_state = deepcopy(state) blocks = [] - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) blocks += new_blocks check_finality(test_state, prev_state, True, False, False) # In epoch N, JE is set to N, prev JE is set to N-1 - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) blocks += new_blocks check_finality(test_state, prev_state, True, True, True) # In epoch N+1, JE is N, prev JE is N-1, and not enough messages get in to do anything - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, False) blocks += new_blocks check_finality(test_state, prev_state, False, True, False) # In epoch N+2, JE is N, prev JE is N, and enough messages from the previous epoch get in to justify N+1. # N+1 now becomes the JE. Not enough messages from epoch N+2 itself get in to justify N+2 - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) blocks += new_blocks # rule 2 check_finality(test_state, prev_state, True, False, True) # In epoch N+3, LJE is N+1, prev LJE is N, and enough messages get in to justify epochs N+2 and N+3. - prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, True) blocks += new_blocks # rule 3 check_finality(test_state, prev_state, True, True, True) diff --git a/test_libs/pyspec/tests/phase0/test_sanity.py b/test_libs/pyspec/tests/phase0/test_sanity.py index 7f3ee48e1..ad206881d 100644 --- a/test_libs/pyspec/tests/phase0/test_sanity.py +++ b/test_libs/pyspec/tests/phase0/test_sanity.py @@ -3,128 +3,95 @@ from copy import deepcopy import pytest from py_ecc import bls -import eth2spec.phase0.spec as spec from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase0.spec import ( - # constants - ZERO_HASH, - SLOTS_PER_HISTORICAL_ROOT, - # SSZ - Deposit, - Transfer, - VoluntaryExit, - # functions - get_active_validator_indices, - get_beacon_proposer_index, - get_block_root_at_slot, - get_current_epoch, - get_domain, - process_slot, - verify_merkle_branch, - state_transition, - hash, -) + from eth2spec.utils.merkle_minimal import ( calc_merkle_tree_from_leaves, get_merkle_proof, get_merkle_root, ) -from .helpers import ( - advance_slot, - get_balance, - build_deposit_data, - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_state_root, - get_valid_attestation, - get_valid_attester_slashing, - get_valid_proposer_slashing, - next_slot, - privkeys, - pubkeys, -) # mark entire file as 'sanity' pytestmark = pytest.mark.sanity -def test_slot_transition(state): +def test_slot_transition(spec, helpers, state): test_state = deepcopy(state) - process_slot(test_state) - advance_slot(test_state) + spec.process_slot(test_state) + helpers.advance_slot(test_state) assert test_state.slot == state.slot + 1 - assert get_state_root(test_state, state.slot) == state.hash_tree_root() + assert helpers.get_state_root(test_state, state.slot) == state.hash_tree_root() return test_state -def test_empty_block_transition(state): +def test_empty_block_transition(spec, helpers, state): test_state = deepcopy(state) - block = build_empty_block_for_next_slot(test_state) - state_transition(test_state, block) + block = helpers.build_empty_block_for_next_slot(test_state) + spec.state_transition(test_state, block) assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1 - assert get_block_root_at_slot(test_state, state.slot) == block.parent_root + assert spec.get_block_root_at_slot(test_state, state.slot) == block.parent_root return state, [block], test_state -def test_skipped_slots(state): +def test_skipped_slots(spec, helpers, state): test_state = deepcopy(state) - block = build_empty_block_for_next_slot(test_state) + block = helpers.build_empty_block_for_next_slot(test_state) block.slot += 3 - state_transition(test_state, block) + spec.state_transition(test_state, block) assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.parent_root + assert spec.get_block_root_at_slot(test_state, slot) == block.parent_root return state, [block], test_state -def test_empty_epoch_transition(state): +def test_empty_epoch_transition(spec, helpers, state): test_state = deepcopy(state) - block = build_empty_block_for_next_slot(test_state) + block = helpers.build_empty_block_for_next_slot(test_state) block.slot += spec.SLOTS_PER_EPOCH - state_transition(test_state, block) + spec.state_transition(test_state, block) assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.parent_root + assert spec.get_block_root_at_slot(test_state, slot) == block.parent_root return state, [block], test_state -def test_empty_epoch_transition_not_finalizing(state): +def test_empty_epoch_transition_not_finalizing(spec, helpers, state): test_state = deepcopy(state) - block = build_empty_block_for_next_slot(test_state) + block = helpers.build_empty_block_for_next_slot(test_state) block.slot += spec.SLOTS_PER_EPOCH * 5 - state_transition(test_state, block) + spec.state_transition(test_state, block) assert test_state.slot == block.slot - assert test_state.finalized_epoch < get_current_epoch(test_state) - 4 + assert test_state.finalized_epoch < spec.get_current_epoch(test_state) - 4 for index in range(len(test_state.validator_registry)): - assert get_balance(test_state, index) < get_balance(state, index) + assert helpers.get_balance(test_state, index) < helpers.get_balance(state, index) return state, [block], test_state -def test_proposer_slashing(state): +def test_proposer_slashing(spec, helpers, state): test_state = deepcopy(state) - proposer_slashing = get_valid_proposer_slashing(state) + proposer_slashing = helpers.get_valid_proposer_slashing(state) validator_index = proposer_slashing.proposer_index # # Add to state via block transition # - block = build_empty_block_for_next_slot(test_state) + block = helpers.build_empty_block_for_next_slot(test_state) block.body.proposer_slashings.append(proposer_slashing) - state_transition(test_state, block) + spec.state_transition(test_state, block) assert not state.validator_registry[validator_index].slashed @@ -133,22 +100,22 @@ def test_proposer_slashing(state): assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward - assert get_balance(test_state, validator_index) < get_balance(state, validator_index) + assert helpers.get_balance(test_state, validator_index) < helpers.get_balance(state, validator_index) return state, [block], test_state -def test_attester_slashing(state): +def test_attester_slashing(spec, helpers, state): test_state = deepcopy(state) - attester_slashing = get_valid_attester_slashing(state) + attester_slashing = helpers.get_valid_attester_slashing(state) validator_index = attester_slashing.attestation_1.custody_bit_0_indices[0] # # Add to state via block transition # - block = build_empty_block_for_next_slot(test_state) + block = helpers.build_empty_block_for_next_slot(test_state) block.body.attester_slashings.append(attester_slashing) - state_transition(test_state, block) + spec.state_transition(test_state, block) assert not state.validator_registry[validator_index].slashed @@ -157,35 +124,35 @@ def test_attester_slashing(state): assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward - assert get_balance(test_state, validator_index) < get_balance(state, validator_index) + assert helpers.get_balance(test_state, validator_index) < helpers.get_balance(state, validator_index) - proposer_index = get_beacon_proposer_index(test_state) + proposer_index = spec.get_beacon_proposer_index(test_state) # gained whistleblower reward assert ( - get_balance(test_state, proposer_index) > - get_balance(state, proposer_index) + helpers.get_balance(test_state, proposer_index) > + helpers.get_balance(state, proposer_index) ) return state, [block], test_state -def test_deposit_in_block(state): +def test_deposit_in_block(spec, helpers, state): pre_state = deepcopy(state) - test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) index = len(test_deposit_data_leaves) - pubkey = pubkeys[index] - privkey = privkeys[index] - deposit_data = build_deposit_data(pre_state, pubkey, privkey, spec.MAX_EFFECTIVE_BALANCE) + pubkey = helpers.pubkeys[index] + privkey = helpers.privkeys[index] + deposit_data = helpers.build_deposit_data(pre_state, pubkey, privkey, spec.MAX_EFFECTIVE_BALANCE) item = deposit_data.hash_tree_root() test_deposit_data_leaves.append(item) tree = calc_merkle_tree_from_leaves(tuple(test_deposit_data_leaves)) root = get_merkle_root((tuple(test_deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=index)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) - deposit = Deposit( + deposit = spec.Deposit( proof=list(proof), index=index, data=deposit_data, @@ -194,27 +161,27 @@ def test_deposit_in_block(state): pre_state.latest_eth1_data.deposit_root = root pre_state.latest_eth1_data.deposit_count = len(test_deposit_data_leaves) post_state = deepcopy(pre_state) - block = build_empty_block_for_next_slot(post_state) + block = helpers.build_empty_block_for_next_slot(post_state) block.body.deposits.append(deposit) - state_transition(post_state, block) + spec.state_transition(post_state, block) assert len(post_state.validator_registry) == len(state.validator_registry) + 1 assert len(post_state.balances) == len(state.balances) + 1 - assert get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE - assert post_state.validator_registry[index].pubkey == pubkeys[index] + assert helpers.get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE + assert post_state.validator_registry[index].pubkey == helpers.pubkeys[index] return pre_state, [block], post_state -def test_deposit_top_up(state): +def test_deposit_top_up(spec, helpers, state): pre_state = deepcopy(state) - test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry) + test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 - pubkey = pubkeys[validator_index] - privkey = privkeys[validator_index] - deposit_data = build_deposit_data(pre_state, pubkey, privkey, amount) + pubkey = helpers.pubkeys[validator_index] + privkey = helpers.privkeys[validator_index] + deposit_data = helpers.build_deposit_data(pre_state, pubkey, privkey, amount) merkle_index = len(test_deposit_data_leaves) item = deposit_data.hash_tree_root() @@ -222,9 +189,9 @@ def test_deposit_top_up(state): tree = calc_merkle_tree_from_leaves(tuple(test_deposit_data_leaves)) root = get_merkle_root((tuple(test_deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=merkle_index)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, merkle_index, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, merkle_index, root) - deposit = Deposit( + deposit = spec.Deposit( proof=list(proof), index=merkle_index, data=deposit_data, @@ -232,31 +199,31 @@ def test_deposit_top_up(state): pre_state.latest_eth1_data.deposit_root = root pre_state.latest_eth1_data.deposit_count = len(test_deposit_data_leaves) - block = build_empty_block_for_next_slot(pre_state) + block = helpers.build_empty_block_for_next_slot(pre_state) block.body.deposits.append(deposit) - pre_balance = get_balance(pre_state, validator_index) + pre_balance = helpers.get_balance(pre_state, validator_index) post_state = deepcopy(pre_state) - state_transition(post_state, block) + spec.state_transition(post_state, block) assert len(post_state.validator_registry) == len(pre_state.validator_registry) assert len(post_state.balances) == len(pre_state.balances) - assert get_balance(post_state, validator_index) == pre_balance + amount + assert helpers.get_balance(post_state, validator_index) == pre_balance + amount return pre_state, [block], post_state -def test_attestation(state): +def test_attestation(spec, helpers, state): state.slot = spec.SLOTS_PER_EPOCH test_state = deepcopy(state) - attestation = get_valid_attestation(state) + attestation = helpers.get_valid_attestation(state) # # Add to state via block transition # - attestation_block = build_empty_block_for_next_slot(test_state) + attestation_block = helpers.build_empty_block_for_next_slot(test_state) attestation_block.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation_block.body.attestations.append(attestation) - state_transition(test_state, attestation_block) + spec.state_transition(test_state, attestation_block) assert len(test_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1 @@ -266,9 +233,9 @@ def test_attestation(state): # pre_current_epoch_attestations = deepcopy(test_state.current_epoch_attestations) - epoch_block = build_empty_block_for_next_slot(test_state) + epoch_block = helpers.build_empty_block_for_next_slot(test_state) epoch_block.slot += spec.SLOTS_PER_EPOCH - state_transition(test_state, epoch_block) + spec.state_transition(test_state, epoch_block) assert len(test_state.current_epoch_attestations) == 0 assert test_state.previous_epoch_attestations == pre_current_epoch_attestations @@ -276,11 +243,11 @@ def test_attestation(state): return state, [attestation_block, epoch_block], test_state -def test_voluntary_exit(state): +def test_voluntary_exit(spec, helpers, state): pre_state = deepcopy(state) - validator_index = get_active_validator_indices( + validator_index = spec.get_active_validator_indices( pre_state, - get_current_epoch(pre_state) + spec.get_current_epoch(pre_state) )[-1] # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -288,14 +255,14 @@ def test_voluntary_exit(state): post_state = deepcopy(pre_state) - voluntary_exit = VoluntaryExit( - epoch=get_current_epoch(pre_state), + voluntary_exit = spec.VoluntaryExit( + epoch=spec.get_current_epoch(pre_state), validator_index=validator_index, ) voluntary_exit.signature = bls.sign( message_hash=signing_root(voluntary_exit), - privkey=privkeys[validator_index], - domain=get_domain( + privkey=helpers.privkeys[validator_index], + domain=spec.get_domain( state=pre_state, domain_type=spec.DOMAIN_VOLUNTARY_EXIT, ) @@ -304,37 +271,37 @@ def test_voluntary_exit(state): # # Add to state via block transition # - initiate_exit_block = build_empty_block_for_next_slot(post_state) + initiate_exit_block = helpers.build_empty_block_for_next_slot(post_state) initiate_exit_block.body.voluntary_exits.append(voluntary_exit) - state_transition(post_state, initiate_exit_block) + spec.state_transition(post_state, initiate_exit_block) assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH # # Process within epoch transition # - exit_block = build_empty_block_for_next_slot(post_state) + exit_block = helpers.build_empty_block_for_next_slot(post_state) exit_block.slot += spec.SLOTS_PER_EPOCH - state_transition(post_state, exit_block) + spec.state_transition(post_state, exit_block) assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH return pre_state, [initiate_exit_block, exit_block], post_state -def test_transfer(state): +def test_transfer(spec, helpers, state): # overwrite default 0 to test spec.apply_constants_preset({"MAX_TRANSFERS": 1}) pre_state = deepcopy(state) - current_epoch = get_current_epoch(pre_state) - sender_index = get_active_validator_indices(pre_state, current_epoch)[-1] - recipient_index = get_active_validator_indices(pre_state, current_epoch)[0] - transfer_pubkey = pubkeys[-1] - transfer_privkey = privkeys[-1] - amount = get_balance(pre_state, sender_index) - pre_transfer_recipient_balance = get_balance(pre_state, recipient_index) - transfer = Transfer( + current_epoch = spec.get_current_epoch(pre_state) + sender_index = spec.get_active_validator_indices(pre_state, current_epoch)[-1] + recipient_index = spec.get_active_validator_indices(pre_state, current_epoch)[0] + transfer_pubkey = helpers.pubkeys[-1] + transfer_privkey = helpers.privkeys[-1] + amount = helpers.get_balance(pre_state, sender_index) + pre_transfer_recipient_balance = helpers.get_balance(pre_state, recipient_index) + transfer = spec.Transfer( sender=sender_index, recipient=recipient_index, amount=amount, @@ -345,7 +312,7 @@ def test_transfer(state): transfer.signature = bls.sign( message_hash=signing_root(transfer), privkey=transfer_privkey, - domain=get_domain( + domain=spec.get_domain( state=pre_state, domain_type=spec.DOMAIN_TRANSFER, ) @@ -353,7 +320,7 @@ def test_transfer(state): # ensure withdrawal_credentials reproducable pre_state.validator_registry[sender_index].withdrawal_credentials = ( - spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(transfer_pubkey)[1:] + spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(transfer_pubkey)[1:] ) # un-activate so validator can transfer pre_state.validator_registry[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH @@ -362,21 +329,21 @@ def test_transfer(state): # # Add to state via block transition # - block = build_empty_block_for_next_slot(post_state) + block = helpers.build_empty_block_for_next_slot(post_state) block.body.transfers.append(transfer) - state_transition(post_state, block) + spec.state_transition(post_state, block) - sender_balance = get_balance(post_state, sender_index) - recipient_balance = get_balance(post_state, recipient_index) + sender_balance = helpers.get_balance(post_state, sender_index) + recipient_balance = helpers.get_balance(post_state, recipient_index) assert sender_balance == 0 assert recipient_balance == pre_transfer_recipient_balance + amount return pre_state, [block], post_state -def test_balance_driven_status_transitions(state): - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[-1] +def test_balance_driven_status_transitions(spec, helpers, state): + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH @@ -387,32 +354,32 @@ def test_balance_driven_status_transitions(state): # # trigger epoch transition # - block = build_empty_block_for_next_slot(post_state) + block = helpers.build_empty_block_for_next_slot(post_state) block.slot += spec.SLOTS_PER_EPOCH - state_transition(post_state, block) + spec.state_transition(post_state, block) assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH return state, [block], post_state -def test_historical_batch(state): +def test_historical_batch(spec, helpers, state): state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1 post_state = deepcopy(state) - block = build_empty_block_for_next_slot(post_state) + block = helpers.build_empty_block_for_next_slot(post_state) - state_transition(post_state, block) + spec.state_transition(post_state, block) assert post_state.slot == block.slot - assert get_current_epoch(post_state) % (spec.SLOTS_PER_HISTORICAL_ROOT // spec.SLOTS_PER_EPOCH) == 0 + assert spec.get_current_epoch(post_state) % (spec.SLOTS_PER_HISTORICAL_ROOT // spec.SLOTS_PER_EPOCH) == 0 assert len(post_state.historical_roots) == len(state.historical_roots) + 1 return state, [block], post_state -def test_eth1_data_votes(state): +def test_eth1_data_votes(spec, helpers, state): post_state = deepcopy(state) expected_votes = 0 @@ -420,14 +387,14 @@ def test_eth1_data_votes(state): blocks = [] for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): - block = build_empty_block_for_next_slot(post_state) - state_transition(post_state, block) + block = helpers.build_empty_block_for_next_slot(post_state) + spec.state_transition(post_state, block) expected_votes += 1 assert len(post_state.eth1_data_votes) == expected_votes blocks.append(block) - block = build_empty_block_for_next_slot(post_state) - state_transition(post_state, block) + block = helpers.build_empty_block_for_next_slot(post_state) + spec.state_transition(post_state, block) blocks.append(block) assert post_state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 From b1711b4ff1399461d0832ae7206ecf06b1312160 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 12:10:08 +0200 Subject: [PATCH 12/55] Implements parameterised phase1 tests --- .gitignore | 1 + Makefile | 3 +- .../test_phase0_block_processing.py | 7 ++ ...est_process_early_derived_secret_reveal.py | 72 ++++++++----------- test_libs/pyspec/tests/phase1/conftest.py | 23 ++++-- .../phase1/epoch_processing/test_phase0.py | 2 + test_libs/pyspec/tests/phase1/helpers.py | 16 +---- .../pyspec/tests/phase1/helpers_phase1.py | 52 -------------- .../pyspec/tests/phase1/test_finality.py | 25 +------ test_libs/pyspec/tests/phase1/test_sanity.py | 66 +---------------- 10 files changed, 60 insertions(+), 207 deletions(-) create mode 100644 test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py create mode 100644 test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py delete mode 100644 test_libs/pyspec/tests/phase1/helpers_phase1.py diff --git a/.gitignore b/.gitignore index 3dd86fc80..c6b39955f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ eth2.0-spec-tests/ # Dynamically built from Markdown spec test_libs/pyspec/eth2spec/phase0/spec.py +test_libs/pyspec/eth2spec/phase1/spec.py diff --git a/Makefile b/Makefile index 49460bdf1..c3ec21280 100644 --- a/Makefile +++ b/Makefile @@ -38,8 +38,7 @@ gen_yaml_tests: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_TARGETS) install_test: cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install -r requirements-testing.txt; -test: $(PY_SPEC_ALL_TARGETS) - cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest . +test: test_phase0 test_phase1 test_phase0: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest tests/phase0 diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py new file mode 100644 index 000000000..246ba163c --- /dev/null +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py @@ -0,0 +1,7 @@ +from tests.phase0.block_processing.test_process_attestation import * +from tests.phase0.block_processing.test_process_attester_slashing import * +from tests.phase0.block_processing.test_process_block_header import * +from tests.phase0.block_processing.test_process_deposit import * +from tests.phase0.block_processing.test_process_proposer_slashing import * +from tests.phase0.block_processing.test_process_transfer import * +from tests.phase0.block_processing.test_voluntary_exit import * diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index 6661e883f..e3cf30ef3 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -1,22 +1,10 @@ from copy import deepcopy import pytest -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - get_current_epoch, - process_early_derived_secret_reveal, - RANDAO_PENALTY_EPOCHS, - CUSTODY_PERIOD_TO_RANDAO_PADDING, - EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, -) -from tests.phase1.helpers import ( - get_valid_early_derived_secret_reveal, -) - #mark entire file as 'randao_key_reveals' pytestmark = pytest.mark.randao_key_reveals -def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): +def terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, valid=True): """ Run ``process_randao_key_reveal`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -25,14 +13,14 @@ def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=T if not valid: with pytest.raises(AssertionError): - process_early_derived_secret_reveal(post_state, randao_key_reveal) + spec.process_early_derived_secret_reveal(post_state, randao_key_reveal) return state, None - process_early_derived_secret_reveal(post_state, randao_key_reveal) + spec.process_early_derived_secret_reveal(post_state, randao_key_reveal) slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] - if randao_key_reveal.epoch >= get_current_epoch(state) + 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.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH @@ -46,63 +34,63 @@ def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=T return state, post_state -def test_success(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state) +def test_success(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal) return pre_state, randao_key_reveal, post_state -def test_reveal_from_current_epoch(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) +def test_reveal_from_current_epoch(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state @pytest.mark.skip(reason="Not currently possible as we are testing at epoch 0") -def test_reveal_from_past_epoch(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) - 1) +def test_reveal_from_past_epoch(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) - 1) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state -def test_reveal_with_custody_padding(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) +def test_reveal_with_custody_padding(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state -def test_reveal_with_custody_padding_minus_one(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) +def test_reveal_with_custody_padding_minus_one(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state -def test_double_reveal(state): +def test_double_reveal(spec, helpers, state): - randao_key_reveal1 = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + RANDAO_PENALTY_EPOCHS + 1) - pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) + randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1) + pre_state, intermediate_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal1) - randao_key_reveal2 = get_valid_early_derived_secret_reveal(intermediate_state, get_current_epoch(pre_state) + RANDAO_PENALTY_EPOCHS + 1) - _, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal(intermediate_state, spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1) + _, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, intermediate_state, randao_key_reveal2, False) return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state -def test_revealer_is_slashed(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state)) +def test_revealer_is_slashed(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) state.validator_registry[randao_key_reveal.revealed_index].slashed = True - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state -def test_far_future_epoch(state): - randao_key_reveal = get_valid_early_derived_secret_reveal(state, get_current_epoch(state) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) +def test_far_future_epoch(spec, helpers, state): + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index c73f25c1b..4af3451a5 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -1,15 +1,12 @@ import pytest -from eth2spec.phase1 import spec +from eth2spec.phase1 import spec as _spec from preset_loader import loader -from tests.phase0.helpers import ( - create_genesis_state, -) +from tests.phase1 import helpers as _helpers from tests.phase0.conftest import ( pytest_addoption, - num_validators, deposit_data_leaves, ) @@ -18,9 +15,21 @@ from tests.phase0.conftest import ( def config(request): config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) - spec.apply_constants_preset(presets) + _spec.apply_constants_preset(presets) + +@pytest.fixture +def num_validators(config): + return _spec.SLOTS_PER_EPOCH * 8 #This is redefined so that the BeaconState is the new SSZ Object @pytest.fixture def state(num_validators, deposit_data_leaves): - return create_genesis_state(num_validators, deposit_data_leaves) + return _helpers.create_genesis_state(num_validators, deposit_data_leaves) + +@pytest.fixture +def spec(): + return _spec + +@pytest.fixture +def helpers(): + return _helpers diff --git a/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py b/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py new file mode 100644 index 000000000..ec3012560 --- /dev/null +++ b/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py @@ -0,0 +1,2 @@ +from tests.phase0.epoch_processing.test_process_crosslinks import * +from tests.phase0.epoch_processing.test_process_registry_updates import * diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index 8520ce9d7..b56266617 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -3,7 +3,6 @@ from py_ecc import bls import eth2spec.phase1.spec as spec from eth2spec.phase1.spec import ( # constants - ZERO_HASH, CUSTODY_PERIOD_TO_RANDAO_PADDING, # SSZ EarlyDerivedSecretReveal, @@ -14,20 +13,7 @@ from eth2spec.phase1.spec import ( hash_tree_root, ) -from tests.phase0.helpers import ( - advance_slot, - get_balance, - build_deposit_data, - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_state_root, - get_valid_attestation, - get_valid_attester_slashing, - get_valid_proposer_slashing, - next_slot, - privkeys, - pubkeys, -) +from tests.phase0.helpers import * def get_valid_early_derived_secret_reveal(state, epoch=None): current_epoch = get_current_epoch(state) diff --git a/test_libs/pyspec/tests/phase1/helpers_phase1.py b/test_libs/pyspec/tests/phase1/helpers_phase1.py deleted file mode 100644 index 5b67e9aa6..000000000 --- a/test_libs/pyspec/tests/phase1/helpers_phase1.py +++ /dev/null @@ -1,52 +0,0 @@ -from py_ecc import bls - -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - # constants - ZERO_HASH, - CUSTODY_PERIOD_TO_RANDAO_PADDING, - # SSZ - EarlyDerivedSecretReveal, - # functions - get_active_validator_indices, - get_current_epoch, - get_domain, - hash_tree_root, -) - -from .helpers import privkeys - -def get_valid_early_derived_secret_reveal(state, epoch=None): - current_epoch = get_current_epoch(state) - revealed_index = get_active_validator_indices(state, current_epoch)[-1] - masker_index = get_active_validator_indices(state, current_epoch)[0] - - if epoch is None: - epoch = current_epoch + CUSTODY_PERIOD_TO_RANDAO_PADDING - - reveal = bls.sign( - message_hash=hash_tree_root(epoch), - privkey=privkeys[revealed_index], - domain=get_domain( - state=state, - domain_type=spec.DOMAIN_RANDAO, - message_epoch=epoch, - ), - ) - mask = bls.sign( - message_hash=hash_tree_root(epoch), - privkey=privkeys[masker_index], - domain=get_domain( - state=state, - domain_type=spec.DOMAIN_RANDAO, - message_epoch=epoch, - ), - ) - - return EarlyDerivedSecretReveal( - revealed_index=revealed_index, - epoch=epoch, - reveal=reveal, - masker_index=masker_index, - mask=mask, - ) diff --git a/test_libs/pyspec/tests/phase1/test_finality.py b/test_libs/pyspec/tests/phase1/test_finality.py index 4b57c9493..1e4e0374a 100644 --- a/test_libs/pyspec/tests/phase1/test_finality.py +++ b/test_libs/pyspec/tests/phase1/test_finality.py @@ -1,27 +1,4 @@ -from copy import deepcopy - import pytest -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - state_transition, -) - -from tests.phase0.helpers import ( - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_current_epoch, - get_epoch_start_slot, - get_valid_attestation, - next_epoch, -) - -from tests.phase0.test_finality import ( - pytestmark, - check_finality, - test_finality_rule_1, - test_finality_rule_2, - test_finality_rule_3, - test_finality_rule_4, -) +from tests.phase0.test_finality import * diff --git a/test_libs/pyspec/tests/phase1/test_sanity.py b/test_libs/pyspec/tests/phase1/test_sanity.py index 45a08bd0e..a9b4d7190 100644 --- a/test_libs/pyspec/tests/phase1/test_sanity.py +++ b/test_libs/pyspec/tests/phase1/test_sanity.py @@ -1,68 +1,4 @@ -from copy import deepcopy - import pytest -from py_ecc import bls -import eth2spec.phase1.spec as spec -from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase1.spec import ( - # constants - ZERO_HASH, - SLOTS_PER_HISTORICAL_ROOT, - # SSZ - Deposit, - Transfer, - VoluntaryExit, - # functions - get_active_validator_indices, - get_beacon_proposer_index, - get_block_root_at_slot, - get_current_epoch, - get_domain, - process_slot, - verify_merkle_branch, - state_transition, - hash, -) -from eth2spec.utils.merkle_minimal import ( - calc_merkle_tree_from_leaves, - get_merkle_proof, - get_merkle_root, -) -from .helpers import ( - advance_slot, - get_balance, - build_deposit_data, - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_state_root, - get_valid_attestation, - get_valid_attester_slashing, - get_valid_proposer_slashing, - next_slot, - privkeys, - pubkeys, -) - - -# mark entire file as 'sanity' -pytestmark = pytest.mark.sanity - -from tests.phase0.test_sanity import ( - test_slot_transition, - test_empty_block_transition, - test_skipped_slots, - test_empty_epoch_transition, - test_empty_epoch_transition_not_finalizing, - test_proposer_slashing, - test_attester_slashing, - test_deposit_in_block, - test_deposit_top_up, - test_attestation, - test_voluntary_exit, - test_transfer, - test_balance_driven_status_transitions, - test_historical_batch, - test_eth1_data_votes, -) +from tests.phase0.test_sanity import * From 3e085947b7416d82503c7fc8e8674ca002798ed8 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 12:38:50 +0200 Subject: [PATCH 13/55] Linted :) --- .../eth2spec/phase1/state_transition.py | 19 ++++++------------- .../pyspec/eth2spec/utils/minimal_ssz.py | 13 ++++++++----- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/test_libs/pyspec/eth2spec/phase1/state_transition.py b/test_libs/pyspec/eth2spec/phase1/state_transition.py index 7e6411287..87b2e1c12 100644 --- a/test_libs/pyspec/eth2spec/phase1/state_transition.py +++ b/test_libs/pyspec/eth2spec/phase1/state_transition.py @@ -1,11 +1,5 @@ from . import spec -from typing import ( - Any, - Callable, - List -) - from .spec import ( BeaconState, BeaconBlock, @@ -13,18 +7,14 @@ from .spec import ( ) from eth2spec.phase0.state_transition import ( - expected_deposit_count, process_operation_type, process_operations as process_operations_phase0, - process_block as process_block_phase0, - process_epoch_transition as process_epoch_transition_phase0, - state_transition_to as state_transition_to_phase0, - state_transition as state_transition_phase0 ) + def process_operations(state: BeaconState, block: BeaconBlock) -> None: process_operations_phase0(state, block) - + process_operation_type( state, block.body.custody_key_reveals, @@ -39,6 +29,7 @@ def process_operations(state: BeaconState, block: BeaconBlock) -> None: spec.process_early_derived_secret_reveal, ) + def process_block(state: BeaconState, block: BeaconBlock, verify_state_root: bool=False) -> None: @@ -50,6 +41,7 @@ def process_block(state: BeaconState, if verify_state_root: spec.verify_block_state_root(state, block) + def process_epoch_transition(state: BeaconState) -> None: spec.process_justification_and_finalization(state) spec.process_crosslinks(state) @@ -62,6 +54,7 @@ def process_epoch_transition(state: BeaconState) -> None: spec.process_final_updates(state) spec.after_process_final_updates(state) + def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState: while state.slot < up_to: spec.cache_state(state) @@ -74,4 +67,4 @@ def state_transition(state: BeaconState, block: BeaconBlock, verify_state_root: bool=False) -> BeaconState: state_transition_to(state, block.slot) - process_block(state, block, verify_state_root) \ No newline at end of file + process_block(state, block, verify_state_root) diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index 8a210f41b..57d9579d9 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -8,12 +8,13 @@ ZERO_CHUNK = b'\x00' * BYTES_PER_CHUNK cached_typedefs = {} + def SSZType(name, fields): class SSZObject(): - if name != None: + if name is not None: __name__ = name __qualname__ = name - + def __init__(self, **kwargs): for f, t in fields.items(): if f not in kwargs: @@ -32,7 +33,7 @@ def SSZType(name, fields): for field in self.fields: output.append(f'{field}: {repr(getattr(self, field))},') return "\n".join(output) - + def __repr__(self): return name + "(**{\n " + str(self).replace("\n", "\n ") + "\n})" @@ -43,17 +44,19 @@ def SSZType(name, fields): return hash_tree_root(self, self.__class__) SSZObject.fields = fields - - if name != None: + + if name is not None: cached_typedefs[name] = SSZObject return SSZObject + def SSZTypeExtension(original_type, new_fields): typedef = cached_typedefs[original_type] typedef.fields.update(new_fields) return typedef + class Vector(): def __init__(self, items): self.items = items From 49d708e44bba654c779b000358ec41618756a7f8 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 12:51:36 +0200 Subject: [PATCH 14/55] Ok, lets at least pass tests :/ --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c3ec21280..2ddc82e68 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,9 @@ test_phase1: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; python -m pytest tests/phase1 citest: $(PY_SPEC_ALL_TARGETS) - cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; python -m pytest --junitxml=test-reports/eth2spec/test_results.xml . + cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; \ + python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase0; \ + python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase1 install_lint: cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.5.0 From 14ea7d9f40dfd0cb485e09f752a783549d2b3661 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 16:36:35 +0200 Subject: [PATCH 15/55] new spec buildign stratergy --- Makefile | 6 +- scripts/{phase0 => }/__init__.py | 0 scripts/build_spec.py | 196 ++++++++++++++++++++++++ scripts/{phase0 => }/function_puller.py | 0 scripts/phase0/build_spec.py | 143 ----------------- 5 files changed, 199 insertions(+), 146 deletions(-) rename scripts/{phase0 => }/__init__.py (100%) create mode 100644 scripts/build_spec.py rename scripts/{phase0 => }/function_puller.py (100%) delete mode 100644 scripts/phase0/build_spec.py diff --git a/Makefile b/Makefile index 2ddc82e68..a262ac5e1 100644 --- a/Makefile +++ b/Makefile @@ -67,11 +67,11 @@ phase0: $(PY_SPEC_PHASE_0_TARGETS) # "make phase1" to create pyspec for phase1 phase1: $(PY_SPEC_PHASE_1_TARGETS) -$(PY_SPEC_DIR)/eth2spec/phase0/spec.py: $(PY_SPEC_PHASE_0_DEPS) - python3 $(SCRIPT_DIR)/phase0/build_spec.py $(SPEC_DIR)/core/0_beacon-chain.md $@ +$(PY_SPEC_PHASE_0_TARGETS): $(PY_SPEC_PHASE_0_DEPS) + python3 $(SCRIPT_DIR)/build_spec.py -p0 $(SPEC_DIR)/core/0_beacon-chain.md $@ $(PY_SPEC_DIR)/eth2spec/phase1/spec.py: $(PY_SPEC_PHASE_1_DEPS) - python3 $(SCRIPT_DIR)/phase0/build_spec.py -p1 $(SPEC_DIR)/core/1_custody-game.md $@ + python3 $(SCRIPT_DIR)/build_spec.py -p1 $(SPEC_DIR)/core/0_beacon-chain.md $(SPEC_DIR)/core/1_custody-game.md $@ CURRENT_DIR = ${CURDIR} diff --git a/scripts/phase0/__init__.py b/scripts/__init__.py similarity index 100% rename from scripts/phase0/__init__.py rename to scripts/__init__.py diff --git a/scripts/build_spec.py b/scripts/build_spec.py new file mode 100644 index 000000000..c77a8b82f --- /dev/null +++ b/scripts/build_spec.py @@ -0,0 +1,196 @@ +import sys +import re +import function_puller +from argparse import ArgumentParser +from typing import Tuple, List + + +def split_retain_delimiter(regex_pattern: str, text: str) -> List[str]: + ''' + Splits a string based on regex, but down not remove the matched text + ''' + find_pattern = r'%s.*?(?=%s|$)' % (regex_pattern, regex_pattern) + return re.findall(find_pattern, text, re.DOTALL) + + +def inserter(oldfile: str, newfile: str) -> Tuple[str, str]: + ''' + Searches for occurrences of @LabelName in oldfile and replaces them with instances of code wraped as follows: + # begin insert @LabelName + def foo(bar): + return bar + # end insert @LabelName + ''' + new_insert_objects = re.split(r"(# begin insert |# end insert @[a-zA-Z0-9_]*\n)", newfile) + # Retrieve label from insert objects + def get_labeled_object(labeled_text): + label = re.match(r"@[a-zA-Z0-9_]*\n", labeled_text) + if label is not None: + label = label.group(0) + labeled_text = re.sub(label, '', labeled_text) + return {'label': label, 'text': labeled_text} + new_insert_objects = map(get_labeled_object, new_insert_objects) + # Find and replace labels + newfile = "" + for item in new_insert_objects: + if item['label'] is not None: + oldfile, insertions = re.subn('# %s' % item['label'], item['text'], oldfile) + if insertions == 0: + newfile.join('# begin insert %s/n%s# end insert %s' % (item['label'], item['text'], item['label'])) + elif re.match(r"(# begin insert |# end insert )", item['text']) is None: + newfile += item['text'] + return oldfile, newfile + + +def merger(oldfile:str, newfile:str) -> str: + ''' + Seeks out functions and objects in new and old files. + Replaces old objects with new ones if they exist. + ''' + old_objects = split_retain_delimiter('\n[a-zA-Z]', oldfile) + new_objects = split_retain_delimiter('\n[a-zA-Z]', newfile) + object_regex = r"\n[#@a-zA-Z_0-9]+[\sa-zA-Z_0-9]*[(){}=:'" "]*" + old_object_tuples = list(map(lambda x: [re.match(object_regex, x).group(0),x], old_objects)) + for new_item in new_objects: + found_old = False + for old_item in old_object_tuples: + if old_item[0] == re.match(object_regex, new_item).group(0): + print(old_item[0]) + old_item[1] = new_item + found_old = True + break + if not found_old: + old_object_tuples += [[re.match(object_regex, new_item).group(0), new_item]] + return ''.join(elem for elem in map(lambda x: x[1], old_object_tuples)) + + +def build_phase0_spec(sourcefile, outfile=None): + code_lines = [] + code_lines.append(""" + +from typing import ( + Any, + Dict, + List, + NewType, + Tuple, +) +from eth2spec.utils.minimal_ssz import ( + SSZType, + hash_tree_root, + signing_root, +) +from eth2spec.utils.bls_stub import ( + bls_aggregate_pubkeys, + bls_verify, + bls_verify_multiple, +) +from eth2spec.utils.hash_function import hash + + +# stub, will get overwritten by real var +SLOTS_PER_EPOCH = 64 + +Slot = NewType('Slot', int) # uint64 +Epoch = NewType('Epoch', int) # uint64 +Shard = NewType('Shard', int) # uint64 +ValidatorIndex = NewType('ValidatorIndex', int) # uint64 +Gwei = NewType('Gwei', int) # uint64 +Bytes32 = NewType('Bytes32', bytes) # bytes32 +BLSPubkey = NewType('BLSPubkey', bytes) # bytes48 +BLSSignature = NewType('BLSSignature', bytes) # bytes96 +Store = None +""") + + code_lines += function_puller.get_spec(sourcefile) + + code_lines.append(""" +# Monkey patch validator compute committee code +_compute_committee = compute_committee +committee_cache = {} + + +def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]: + param_hash = (hash_tree_root(indices), seed, index, count) + + if param_hash in committee_cache: + return committee_cache[param_hash] + else: + ret = _compute_committee(indices, seed, index, count) + committee_cache[param_hash] = ret + return ret + + +# Monkey patch hash cache +_hash = hash +hash_cache = {} + + +def hash(x): + if x in hash_cache: + return hash_cache[x] + else: + ret = _hash(x) + hash_cache[x] = ret + return ret + + +# Access to overwrite spec constants based on configuration +def apply_constants_preset(preset: Dict[str, Any]): + global_vars = globals() + for k, v in preset.items(): + global_vars[k] = v + + # Deal with derived constants + global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) + + # Initialize SSZ types again, to account for changed lengths + init_SSZ_types() +""") + + if outfile is not None: + with open(outfile, 'w') as out: + out.write("\n".join(code_lines)) + else: + return "\n".join(code_lines) + + +def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): + phase0_code = build_phase0_spec(phase0_sourcefile) + phase1_code = build_phase0_spec(phase1_sourcefile) + phase0_code, phase1_code = inserter(phase0_code, phase1_code) + phase1_code = merger(phase0_code, phase1_code) + + if outfile is not None: + with open(outfile, 'w') as out: + out.write(phase1_code) + else: + return phase1_code + + +if __name__ == '__main__': + description = ''' +Build the specs from the md docs. +If building phase 0: + 1st argument is input spec.md + 2nd argument is output spec.py + +If building phase 1: + 1st argument is input spec_phase0.md + 2nd argument is input spec_phase1.md + 3rd argument is output spec.py +''' + parser = ArgumentParser(description=description) + parser.add_argument("-p", "--phase", dest="phase", type=int, default=0, help="Build for phase #") + parser.add_argument(dest="files", help="Input and output files", nargs="+") + + args = parser.parse_args() + if args.phase == 0: + build_phase0_spec(*args.files) + elif args.phase == 1: + if len(args.files) == 3: + build_phase1_spec(*args.files) + else: + print(" Phase 1 requires an output as well as 2 input files (phase0.md and phase1.md)") + else: + print("Invalid phase: {0}".format(args.phase)) diff --git a/scripts/phase0/function_puller.py b/scripts/function_puller.py similarity index 100% rename from scripts/phase0/function_puller.py rename to scripts/function_puller.py diff --git a/scripts/phase0/build_spec.py b/scripts/phase0/build_spec.py deleted file mode 100644 index 4faf8cbf6..000000000 --- a/scripts/phase0/build_spec.py +++ /dev/null @@ -1,143 +0,0 @@ -import sys -import function_puller -from optparse import OptionParser - -def build_phase0_spec(sourcefile, outfile): - code_lines = [] - code_lines.append(""" - -from typing import ( - Any, - Dict, - List, - NewType, - Tuple, -) -from eth2spec.utils.minimal_ssz import ( - SSZType, - SSZTypeExtension, - hash_tree_root, - signing_root, -) -from eth2spec.utils.bls_stub import ( - bls_aggregate_pubkeys, - bls_verify, - bls_verify_multiple, -) -from eth2spec.utils.hash_function import hash - - -# stub, will get overwritten by real var -SLOTS_PER_EPOCH = 64 - -Slot = NewType('Slot', int) # uint64 -Epoch = NewType('Epoch', int) # uint64 -Shard = NewType('Shard', int) # uint64 -ValidatorIndex = NewType('ValidatorIndex', int) # uint64 -Gwei = NewType('Gwei', int) # uint64 -Bytes32 = NewType('Bytes32', bytes) # bytes32 -BLSPubkey = NewType('BLSPubkey', bytes) # bytes48 -BLSSignature = NewType('BLSSignature', bytes) # bytes96 -Store = None -""") - - code_lines += function_puller.get_spec(sourcefile) - - code_lines.append(""" -# Monkey patch validator compute committee code -_compute_committee = compute_committee -committee_cache = {} - - -def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]: - param_hash = (hash_tree_root(indices), seed, index, count) - - if param_hash in committee_cache: - return committee_cache[param_hash] - else: - ret = _compute_committee(indices, seed, index, count) - committee_cache[param_hash] = ret - return ret - - -# Monkey patch hash cache -_hash = hash -hash_cache = {} - - -def hash(x): - if x in hash_cache: - return hash_cache[x] - else: - ret = _hash(x) - hash_cache[x] = ret - return ret - - -# Access to overwrite spec constants based on configuration -def apply_constants_preset(preset: Dict[str, Any]): - global_vars = globals() - for k, v in preset.items(): - global_vars[k] = v - - # Deal with derived constants - global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) - - # Initialize SSZ types again, to account for changed lengths - init_SSZ_types() -""") - - with open(outfile, 'w') as out: - out.write("\n".join(code_lines)) - - -def build_phase1_spec(sourcefile, outfile): - code_lines = [] - code_lines.append(""" -from eth2spec.phase0.spec import * -from eth2spec.phase0.spec import apply_constants_preset as apply_constants_preset_phase0 - -""") - - code_lines += function_puller.get_spec(sourcefile) - - code_lines.append(""" -# Access to overwrite spec constants based on configuration -def apply_constants_preset(preset: Dict[str, Any]): - - apply_constants_preset_phase0(preset) - - global_vars = globals() - for k, v in preset.items(): - global_vars[k] = v - - # Deal with derived constants - global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) - - # Initialize SSZ types again, to account for changed lengths - init_SSZ_types() -""") - - with open(outfile, 'w') as out: - out.write("\n".join(code_lines)) - - -if __name__ == '__main__': - parser = OptionParser() - parser.add_option("-p", "--phase", dest="phase", type="int", default=0, - help="Build for phase #") - - (options, args) = parser.parse_args() - - if len(args) < 2: - parser.print_help() - - if options.phase == 0: - build_phase0_spec(args[0], args[1]) - print(args[0]) - print(args[1]) - elif options.phase == 1: - build_phase1_spec(args[0], args[1]) - else: - print("Invalid phase: {0}".format(options["phase"])) - From f6f7d53735ee456264cae0fe4a0dc5883f4164d6 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 17:14:07 +0200 Subject: [PATCH 16/55] simplify function_puller --- scripts/function_puller.py | 20 ++------- scripts/phase0/function_puller.py | 75 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 scripts/phase0/function_puller.py diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 418eb05b1..787c2ff06 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -2,26 +2,16 @@ import sys from typing import List -def get_spec(file_name: str, phase:int = 0) -> List[str]: +def get_spec(file_name: str) -> List[str]: code_lines = [] pulling_from = None current_name = None current_typedef = None - is_update_section = False - update_section_depth = None type_defs = [] for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': current_name = line[line[:-1].rfind('`') + 1: -1] - if pulling_from is None and len(line) > 0 and line[0] == '#' and line.endswith('updates'): - is_update_section = True - update_section_depth = max(i for i in range(10) if line.startswith('#' * i)) - elif pulling_from is None and len(line) > 0 and line[0] == '#' and is_update_section: - section_depth = max(i for i in range(10) if line.startswith('#' * i)) - if section_depth <= update_section_depth: - is_update_section = False - update_section_depth = None if line[:9] == '```python': assert pulling_from is None pulling_from = linenum + 1 @@ -38,12 +28,8 @@ def get_spec(file_name: str, phase:int = 0) -> List[str]: current_typedef = None else: if pulling_from == linenum and line == '{': - if is_update_section: - code_lines.append('%s = SSZTypeExtension("%s", {' % (current_name, current_name)) - current_typedef = ['global_vars["%s"] = SSZTypeExtension("%s", {' % (current_name, current_name)] - else: - code_lines.append('%s = SSZType("%s", {' % (current_name, current_name)) - current_typedef = ['global_vars["%s"] = SSZType("%s", {' % (current_name, current_name)] + code_lines.append('%s = SSZType({' % current_name) + current_typedef = ['global_vars["%s"] = SSZType({' % current_name] elif pulling_from is not None: # Add some whitespace between functions if line[:3] == 'def': diff --git a/scripts/phase0/function_puller.py b/scripts/phase0/function_puller.py new file mode 100644 index 000000000..750f19590 --- /dev/null +++ b/scripts/phase0/function_puller.py @@ -0,0 +1,75 @@ +import sys +from typing import List + + +def get_spec(file_name: str) -> List[str]: + code_lines = [] + pulling_from = None + current_name = None + current_typedef = None + type_defs = [] + for linenum, line in enumerate(open(sys.argv[1]).readlines()): + line = line.rstrip() + if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': + current_name = line[line[:-1].rfind('`') + 1: -1] + if line[:9] == '```python': + assert pulling_from is None + pulling_from = linenum + 1 + elif line[:3] == '```': + if pulling_from is None: + pulling_from = linenum + else: + if current_typedef is not None: + assert code_lines[-1] == '}' + code_lines[-1] = '})' + current_typedef[-1] = '})' + type_defs.append((current_name, current_typedef)) + pulling_from = None + current_typedef = None + else: + if pulling_from == linenum and line == '{': + code_lines.append('%s = SSZType({' % current_name) + current_typedef = ['global_vars["%s"] = SSZType({' % current_name] + elif pulling_from is not None: + # Add some whitespace between functions + if line[:3] == 'def': + code_lines.append('') + code_lines.append('') + code_lines.append(line) + # Remember type def lines + if current_typedef is not None: + current_typedef.append(line) + elif pulling_from is None and len(line) > 0 and line[0] == '|': + row = line[1:].split('|') + if len(row) >= 2: + for i in range(2): + row[i] = row[i].strip().strip('`') + if '`' in row[i]: + row[i] = row[i][:row[i].find('`')] + eligible = True + if row[0][0] not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_': + eligible = False + for c in row[0]: + if c not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789': + eligible = False + if eligible: + code_lines.append(row[0] + ' = ' + (row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890'))) + # Build type-def re-initialization + code_lines.append('\n') + code_lines.append('def init_SSZ_types():') + code_lines.append(' global_vars = globals()') + for ssz_type_name, ssz_type in type_defs: + code_lines.append('') + for type_line in ssz_type: + if len(type_line) > 0: + code_lines.append(' ' + type_line) + code_lines.append('\n') + code_lines.append('ssz_types = [\n') + for (ssz_type_name, _) in type_defs: + code_lines.append(f' {ssz_type_name},\n') + code_lines.append(']') + code_lines.append('\n') + code_lines.append('def get_ssz_type_by_name(name: str) -> SSZType:') + code_lines.append(' return globals()[name]') + code_lines.append('') + return code_lines From 9f2d410a1737973a54f12ddf38832145ef4e9dcd Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 17:15:45 +0200 Subject: [PATCH 17/55] removes old files --- scripts/phase0/function_puller.py | 75 ------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 scripts/phase0/function_puller.py diff --git a/scripts/phase0/function_puller.py b/scripts/phase0/function_puller.py deleted file mode 100644 index 750f19590..000000000 --- a/scripts/phase0/function_puller.py +++ /dev/null @@ -1,75 +0,0 @@ -import sys -from typing import List - - -def get_spec(file_name: str) -> List[str]: - code_lines = [] - pulling_from = None - current_name = None - current_typedef = None - type_defs = [] - for linenum, line in enumerate(open(sys.argv[1]).readlines()): - line = line.rstrip() - if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': - current_name = line[line[:-1].rfind('`') + 1: -1] - if line[:9] == '```python': - assert pulling_from is None - pulling_from = linenum + 1 - elif line[:3] == '```': - if pulling_from is None: - pulling_from = linenum - else: - if current_typedef is not None: - assert code_lines[-1] == '}' - code_lines[-1] = '})' - current_typedef[-1] = '})' - type_defs.append((current_name, current_typedef)) - pulling_from = None - current_typedef = None - else: - if pulling_from == linenum and line == '{': - code_lines.append('%s = SSZType({' % current_name) - current_typedef = ['global_vars["%s"] = SSZType({' % current_name] - elif pulling_from is not None: - # Add some whitespace between functions - if line[:3] == 'def': - code_lines.append('') - code_lines.append('') - code_lines.append(line) - # Remember type def lines - if current_typedef is not None: - current_typedef.append(line) - elif pulling_from is None and len(line) > 0 and line[0] == '|': - row = line[1:].split('|') - if len(row) >= 2: - for i in range(2): - row[i] = row[i].strip().strip('`') - if '`' in row[i]: - row[i] = row[i][:row[i].find('`')] - eligible = True - if row[0][0] not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_': - eligible = False - for c in row[0]: - if c not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789': - eligible = False - if eligible: - code_lines.append(row[0] + ' = ' + (row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890'))) - # Build type-def re-initialization - code_lines.append('\n') - code_lines.append('def init_SSZ_types():') - code_lines.append(' global_vars = globals()') - for ssz_type_name, ssz_type in type_defs: - code_lines.append('') - for type_line in ssz_type: - if len(type_line) > 0: - code_lines.append(' ' + type_line) - code_lines.append('\n') - code_lines.append('ssz_types = [\n') - for (ssz_type_name, _) in type_defs: - code_lines.append(f' {ssz_type_name},\n') - code_lines.append(']') - code_lines.append('\n') - code_lines.append('def get_ssz_type_by_name(name: str) -> SSZType:') - code_lines.append(' return globals()[name]') - code_lines.append('') - return code_lines From 306a613c8a1dcb516fb0901c92e320aff3d2c5aa Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 21:01:32 +0200 Subject: [PATCH 18/55] Simplify minimal SSZ again --- scripts/build_spec.py | 18 ++++++++------- .../pyspec/eth2spec/utils/minimal_ssz.py | 23 +++---------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index c77a8b82f..705808d9f 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -27,7 +27,7 @@ def inserter(oldfile: str, newfile: str) -> Tuple[str, str]: label = re.match(r"@[a-zA-Z0-9_]*\n", labeled_text) if label is not None: label = label.group(0) - labeled_text = re.sub(label, '', labeled_text) + labeled_text = re.sub(label, '', labeled_text) return {'label': label, 'text': labeled_text} new_insert_objects = map(get_labeled_object, new_insert_objects) # Find and replace labels @@ -53,9 +53,8 @@ def merger(oldfile:str, newfile:str) -> str: old_object_tuples = list(map(lambda x: [re.match(object_regex, x).group(0),x], old_objects)) for new_item in new_objects: found_old = False - for old_item in old_object_tuples: + for old_item in old_object_tuples: if old_item[0] == re.match(object_regex, new_item).group(0): - print(old_item[0]) old_item[1] = new_item found_old = True break @@ -67,7 +66,6 @@ def merger(oldfile:str, newfile:str) -> str: def build_phase0_spec(sourcefile, outfile=None): code_lines = [] code_lines.append(""" - from typing import ( Any, Dict, @@ -75,16 +73,19 @@ from typing import ( NewType, Tuple, ) + from eth2spec.utils.minimal_ssz import ( SSZType, hash_tree_root, signing_root, ) + from eth2spec.utils.bls_stub import ( bls_aggregate_pubkeys, bls_verify, bls_verify_multiple, ) + from eth2spec.utils.hash_function import hash @@ -146,6 +147,7 @@ def apply_constants_preset(preset: Dict[str, Any]): # Initialize SSZ types again, to account for changed lengths init_SSZ_types() + """) if outfile is not None: @@ -160,7 +162,7 @@ def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): phase1_code = build_phase0_spec(phase1_sourcefile) phase0_code, phase1_code = inserter(phase0_code, phase1_code) phase1_code = merger(phase0_code, phase1_code) - + if outfile is not None: with open(outfile, 'w') as out: out.write(phase1_code) @@ -172,12 +174,12 @@ if __name__ == '__main__': description = ''' Build the specs from the md docs. If building phase 0: - 1st argument is input spec.md + 1st argument is input spec.md 2nd argument is output spec.py If building phase 1: - 1st argument is input spec_phase0.md - 2nd argument is input spec_phase1.md + 1st argument is input spec_phase0.md + 2nd argument is input spec_phase1.md 3rd argument is output spec.py ''' parser = ArgumentParser(description=description) diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index 57d9579d9..f7784b6de 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -9,12 +9,8 @@ ZERO_CHUNK = b'\x00' * BYTES_PER_CHUNK cached_typedefs = {} -def SSZType(name, fields): +def SSZType(fields): class SSZObject(): - if name is not None: - __name__ = name - __qualname__ = name - def __init__(self, **kwargs): for f, t in fields.items(): if f not in kwargs: @@ -31,12 +27,9 @@ def SSZType(name, fields): def __str__(self): output = [] for field in self.fields: - output.append(f'{field}: {repr(getattr(self, field))},') + output.append(f'{field}: {getattr(self, field)}') return "\n".join(output) - def __repr__(self): - return name + "(**{\n " + str(self).replace("\n", "\n ") + "\n})" - def serialize(self): return serialize_value(self, self.__class__) @@ -44,19 +37,9 @@ def SSZType(name, fields): return hash_tree_root(self, self.__class__) SSZObject.fields = fields - - if name is not None: - cached_typedefs[name] = SSZObject - return SSZObject -def SSZTypeExtension(original_type, new_fields): - typedef = cached_typedefs[original_type] - typedef.fields.update(new_fields) - return typedef - - class Vector(): def __init__(self, items): self.items = items @@ -334,7 +317,7 @@ def truncate(container): key: container.fields[key] for key in field_keys[:-1] } - truncated_class = SSZType(None, truncated_fields) + truncated_class = SSZType(truncated_fields) kwargs = { field: getattr(container, field) for field in field_keys[:-1] From 7c8f83d5e84d04274eb61e3faea9f5d09b727c38 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 16 May 2019 23:52:40 +0200 Subject: [PATCH 19/55] partial combination of phase0 and phase1 implemented --- scripts/build_spec.py | 39 +++++++++++++++++++++++--------------- scripts/function_puller.py | 5 ----- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 705808d9f..a18107528 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -5,12 +5,14 @@ from argparse import ArgumentParser from typing import Tuple, List -def split_retain_delimiter(regex_pattern: str, text: str) -> List[str]: +def split_and_label(regex_pattern: str, text: str) -> List[str]: ''' - Splits a string based on regex, but down not remove the matched text + Splits a string based on regex, but down not remove the matched text. + It subsequently labels the matches with their match ''' - find_pattern = r'%s.*?(?=%s|$)' % (regex_pattern, regex_pattern) - return re.findall(find_pattern, text, re.DOTALL) + find_pattern = r'''%s.*?(?=%s|$)''' % (regex_pattern, regex_pattern) + matches = re.findall(find_pattern, text, re.DOTALL) + return list(map(lambda x: [re.match(regex_pattern, x).group(0), x], matches)) def inserter(oldfile: str, newfile: str) -> Tuple[str, str]: @@ -21,10 +23,10 @@ def inserter(oldfile: str, newfile: str) -> Tuple[str, str]: return bar # end insert @LabelName ''' - new_insert_objects = re.split(r"(# begin insert |# end insert @[a-zA-Z0-9_]*\n)", newfile) + new_insert_objects = re.split(r"(# begin insert |# end insert @[\w\d_]*\n)", newfile) # Retrieve label from insert objects def get_labeled_object(labeled_text): - label = re.match(r"@[a-zA-Z0-9_]*\n", labeled_text) + label = re.match(r"@[\w\d_]*\n", labeled_text) if label is not None: label = label.group(0) labeled_text = re.sub(label, '', labeled_text) @@ -47,20 +49,27 @@ def merger(oldfile:str, newfile:str) -> str: Seeks out functions and objects in new and old files. Replaces old objects with new ones if they exist. ''' - old_objects = split_retain_delimiter('\n[a-zA-Z]', oldfile) - new_objects = split_retain_delimiter('\n[a-zA-Z]', newfile) - object_regex = r"\n[#@a-zA-Z_0-9]+[\sa-zA-Z_0-9]*[(){}=:'" "]*" - old_object_tuples = list(map(lambda x: [re.match(object_regex, x).group(0),x], old_objects)) + object_regex = r'''(?:\n[@\w]+[\s\w]*[='" "\.\w]*)|(?:\s{4}global_vars\["\w+"\])''' + ssz_object_regex = r'''(?:\w+|\s{4}global_vars\["\w+"\]) = SSZType\(\{\n''' + old_objects = split_and_label(object_regex, oldfile) + new_objects = split_and_label(object_regex, newfile) for new_item in new_objects: found_old = False - for old_item in old_object_tuples: - if old_item[0] == re.match(object_regex, new_item).group(0): - old_item[1] = new_item + for index, old_item in enumerate(old_objects): + if old_item[0] == new_item[0]: + ssz_object_match = re.match(ssz_object_regex, new_item[1]) + if ssz_object_match is not None: + new_item[1] = re.sub(ssz_object_regex, '', new_item[1]) + old_item[1] = re.sub(r'\n\w*\}\)', '', old_item[1]) + old_item[1] += new_item[1] + else: + old_item[1] = new_item[1] found_old = True + old_objects[index] = old_item break if not found_old: - old_object_tuples += [[re.match(object_regex, new_item).group(0), new_item]] - return ''.join(elem for elem in map(lambda x: x[1], old_object_tuples)) + old_objects.append(new_item) + return ''.join(elem for elem in map(lambda x: x[1], old_objects)) def build_phase0_spec(sourcefile, outfile=None): diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 787c2ff06..97bc62821 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -64,11 +64,6 @@ def get_spec(file_name: str) -> List[str]: if len(type_line) > 0: code_lines.append(' ' + type_line) code_lines.append('\n') - code_lines.append('ssz_types = [\n') - for (ssz_type_name, _) in type_defs: - code_lines.append(f' {ssz_type_name},\n') - code_lines.append(']') - code_lines.append('\n') code_lines.append('def get_ssz_type_by_name(name: str) -> SSZType:') code_lines.append(' return globals()[name]') code_lines.append('') From 0e2d9e49636e531cd59c182bd93b158d24764e1c Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Sat, 18 May 2019 10:42:04 +0200 Subject: [PATCH 20/55] Function_puller returns objects --- scripts/build_spec.py | 227 +++++++++++++++++++++---------------- scripts/function_puller.py | 71 +++++------- 2 files changed, 161 insertions(+), 137 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index a18107528..cdcbc2456 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -5,6 +5,83 @@ from argparse import ArgumentParser from typing import Tuple, List +IMPORTS = '''from typing import ( + Any, + Dict, + List, + NewType, + Tuple, +) + +from eth2spec.utils.minimal_ssz import ( + SSZType, + hash_tree_root, + signing_root, +) + +from eth2spec.utils.bls_stub import ( + bls_aggregate_pubkeys, + bls_verify, + bls_verify_multiple, +) + +from eth2spec.utils.hash_function import hash +''' +NEW_TYPE_DEFINITIONS = ''' +Slot = NewType('Slot', int) # uint64 +Epoch = NewType('Epoch', int) # uint64 +Shard = NewType('Shard', int) # uint64 +ValidatorIndex = NewType('ValidatorIndex', int) # uint64 +Gwei = NewType('Gwei', int) # uint64 +Bytes32 = NewType('Bytes32', bytes) # bytes32 +BLSPubkey = NewType('BLSPubkey', bytes) # bytes48 +BLSSignature = NewType('BLSSignature', bytes) # bytes96 +Store = None +''' +SUNDRY_FUNCTIONS = ''' +# Monkey patch validator compute committee code +_compute_committee = compute_committee +committee_cache = {} + + +def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]: + param_hash = (hash_tree_root(indices), seed, index, count) + + if param_hash in committee_cache: + return committee_cache[param_hash] + else: + ret = _compute_committee(indices, seed, index, count) + committee_cache[param_hash] = ret + return ret + + +# Monkey patch hash cache +_hash = hash +hash_cache = {} + + +def hash(x): + if x in hash_cache: + return hash_cache[x] + else: + ret = _hash(x) + hash_cache[x] = ret + return ret + + +# Access to overwrite spec constants based on configuration +def apply_constants_preset(preset: Dict[str, Any]): + global_vars = globals() + for k, v in preset.items(): + global_vars[k] = v + + # Deal with derived constants + global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) + + # Initialize SSZ types again, to account for changed lengths + init_SSZ_types() +''' + def split_and_label(regex_pattern: str, text: str) -> List[str]: ''' Splits a string based on regex, but down not remove the matched text. @@ -72,111 +149,71 @@ def merger(oldfile:str, newfile:str) -> str: return ''.join(elem for elem in map(lambda x: x[1], old_objects)) +def objects_to_spec(functions, constants, ssz_objects): + functions_spec = '\n\n'.join(functions.values()) + constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) + ssz_objects_instantiation_spec = '\n'.join(map(lambda x: '%s = SSZType(%s)' % (x, ssz_objects[x][:-1]), ssz_objects)) + ssz_objects_reinitialization_spec = '\n'.join( + map(lambda x: ' global_vars[%s] = SSZType(%s })' % (x, re.sub('( ){4}', ' '*8, ssz_objects[x][:-2])), ssz_objects)) + ssz_objects_reinitialization_spec = ( + 'def init_SSZ_types():\n global_vars = globals()\n' + + ssz_objects_reinitialization_spec + ) + return ( + IMPORTS + + '\n' + NEW_TYPE_DEFINITIONS + + '\n' + constants_spec + + '\n' + ssz_objects_instantiation_spec + + '\n\n\n' + functions_spec + + '\n' + SUNDRY_FUNCTIONS + + '\n\n' + ssz_objects_reinitialization_spec + + '\n' + ) + +def combine_functions(old_funcitons, new_functions): + for key, value in new_functions.items(): + old_funcitons[key] = value + # TODO: Add insert functionality + return old_funcitons + + +def combine_constants(old_constants, new_constants): + for key, value in new_constants.items(): + old_constants[key] = value + return old_constants + +def combine_ssz_objects(old_objects, new_objects): + remove_encasing = lambda x: x[1:-1] + old_objects = map(remove_encasing, old_objects) + new_objects = map(remove_encasing, new_objects) + for key, value in new_objects.items(): + old_objects[key] += value + reapply_encasing = lambda x: '{%s}' %x + return map(reapply_encasing, old_objects) + + def build_phase0_spec(sourcefile, outfile=None): - code_lines = [] - code_lines.append(""" -from typing import ( - Any, - Dict, - List, - NewType, - Tuple, -) - -from eth2spec.utils.minimal_ssz import ( - SSZType, - hash_tree_root, - signing_root, -) - -from eth2spec.utils.bls_stub import ( - bls_aggregate_pubkeys, - bls_verify, - bls_verify_multiple, -) - -from eth2spec.utils.hash_function import hash - - -# stub, will get overwritten by real var -SLOTS_PER_EPOCH = 64 - -Slot = NewType('Slot', int) # uint64 -Epoch = NewType('Epoch', int) # uint64 -Shard = NewType('Shard', int) # uint64 -ValidatorIndex = NewType('ValidatorIndex', int) # uint64 -Gwei = NewType('Gwei', int) # uint64 -Bytes32 = NewType('Bytes32', bytes) # bytes32 -BLSPubkey = NewType('BLSPubkey', bytes) # bytes48 -BLSSignature = NewType('BLSSignature', bytes) # bytes96 -Store = None -""") - - code_lines += function_puller.get_spec(sourcefile) - - code_lines.append(""" -# Monkey patch validator compute committee code -_compute_committee = compute_committee -committee_cache = {} - - -def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]: - param_hash = (hash_tree_root(indices), seed, index, count) - - if param_hash in committee_cache: - return committee_cache[param_hash] - else: - ret = _compute_committee(indices, seed, index, count) - committee_cache[param_hash] = ret - return ret - - -# Monkey patch hash cache -_hash = hash -hash_cache = {} - - -def hash(x): - if x in hash_cache: - return hash_cache[x] - else: - ret = _hash(x) - hash_cache[x] = ret - return ret - - -# Access to overwrite spec constants based on configuration -def apply_constants_preset(preset: Dict[str, Any]): - global_vars = globals() - for k, v in preset.items(): - global_vars[k] = v - - # Deal with derived constants - global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT) - - # Initialize SSZ types again, to account for changed lengths - init_SSZ_types() - -""") - + functions, constants, ssz_objects = function_puller.get_spec(sourcefile) + spec = objects_to_spec(functions, constants, ssz_objects) if outfile is not None: with open(outfile, 'w') as out: - out.write("\n".join(code_lines)) + out.write(spec) else: - return "\n".join(code_lines) + return spec def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): - phase0_code = build_phase0_spec(phase0_sourcefile) - phase1_code = build_phase0_spec(phase1_sourcefile) - phase0_code, phase1_code = inserter(phase0_code, phase1_code) - phase1_code = merger(phase0_code, phase1_code) - + phase0_functions, phase0_constants, phase0_ssz_objects = function_puller.get_spec(phase0_sourcefile) + phase1_functions, phase1_constants, phase1_ssz_objects = function_puller.get_spec(phase1_sourcefile) + functions = combine_functions(phase0_functions, phase1_functions) + constants = combine_constants(phase0_constants, phase1_constants) + ssz_objects = combine_functions(phase0_ssz_objects, phase1_ssz_objects) + spec = objects_to_spec(functions, constants, ssz_objects) if outfile is not None: with open(outfile, 'w') as out: - out.write(phase1_code) + out.write(spec) else: - return phase1_code + return spec if __name__ == '__main__': diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 97bc62821..720f07502 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -1,13 +1,21 @@ import sys +import re from typing import List +from collections import defaultdict -def get_spec(file_name: str) -> List[str]: +FUNCTION_REGEX = r'^def [\w_]*' + + +def get_spec(file_name: str): code_lines = [] - pulling_from = None - current_name = None - current_typedef = None - type_defs = [] + pulling_from = None # line number of start of latest object + current_name = None # most recent section title + functions = defaultdict(str) + constants = {} + ssz_objects = defaultdict(str) + function_matcher = re.compile(FUNCTION_REGEX) + # type_defs = [] for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': @@ -16,29 +24,21 @@ def get_spec(file_name: str) -> List[str]: assert pulling_from is None pulling_from = linenum + 1 elif line[:3] == '```': - if pulling_from is None: - pulling_from = linenum - else: - if current_typedef is not None: - assert code_lines[-1] == '}' - code_lines[-1] = '})' - current_typedef[-1] = '})' - type_defs.append((current_name, current_typedef)) - pulling_from = None - current_typedef = None + pulling_from = None else: - if pulling_from == linenum and line == '{': - code_lines.append('%s = SSZType({' % current_name) - current_typedef = ['global_vars["%s"] = SSZType({' % current_name] - elif pulling_from is not None: - # Add some whitespace between functions - if line[:3] == 'def': - code_lines.append('') - code_lines.append('') - code_lines.append(line) - # Remember type def lines - if current_typedef is not None: - current_typedef.append(line) + # # Handle SSZObjects + # if pulling_from == linenum and line == '{': + # code_lines.append('%s = SSZType({' % current_name) + # Handle function definitions + if pulling_from is not None: + match = function_matcher.match(line) + if match is not None: + current_name = match.group(0) + if function_matcher.match(current_name) is None: + ssz_objects[current_name] += line + '\n' + else: + functions[current_name] += line + '\n' + # Handle constant table entries elif pulling_from is None and len(line) > 0 and line[0] == '|': row = line[1:].split('|') if len(row) >= 2: @@ -53,18 +53,5 @@ def get_spec(file_name: str) -> List[str]: if c not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789': eligible = False if eligible: - code_lines.append(row[0] + ' = ' + (row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890'))) - # Build type-def re-initialization - code_lines.append('\n') - code_lines.append('def init_SSZ_types():') - code_lines.append(' global_vars = globals()') - for ssz_type_name, ssz_type in type_defs: - code_lines.append('') - for type_line in ssz_type: - if len(type_line) > 0: - code_lines.append(' ' + type_line) - code_lines.append('\n') - code_lines.append('def get_ssz_type_by_name(name: str) -> SSZType:') - code_lines.append(' return globals()[name]') - code_lines.append('') - return code_lines + constants[row[0]] = row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890') + return functions, constants, ssz_objects From 725dcf27f584fed5b2df86d66c05c02cb952a247 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 09:47:44 +0200 Subject: [PATCH 21/55] Hella bug-fixes and PEP8 --- specs/core/1_custody-game.md | 68 +++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index ba828dd2c..df4f495be 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -273,7 +273,7 @@ The `empty` function accepts and SSZ type as input and returns an object of that def get_custody_chunk_count(attestation: Attestation) -> int: crosslink_start_epoch = attestation.data.latest_crosslink.epoch crosslink_end_epoch = slot_to_epoch(attestation.data.slot) - crosslink_crosslink_length = min(MAX_EPOCHS_PER_CROSSLINK, end_epoch - start_epoch) + crosslink_crosslink_length = min(MAX_EPOCHS_PER_CROSSLINK, crosslink_end_epoch - crosslink_start_epoch) chunks_per_epoch = 2 * BYTES_PER_SHARD_BLOCK * SLOTS_PER_EPOCH // BYTES_PER_CUSTODY_CHUNK return crosslink_crosslink_length * chunks_per_epoch ``` @@ -283,7 +283,7 @@ def get_custody_chunk_count(attestation: Attestation) -> int: ```python def get_custody_chunk_bit(key: BLSSignature, chunk: bytes) -> bool: # TODO: Replace with something MPC-friendly, e.g. the Legendre symbol - return get_bitfield_bit(hash(challenge.responder_key + chunk), 0) + return get_bitfield_bit(hash(key + chunk), 0) ``` ### `get_chunk_bits_root` @@ -348,8 +348,7 @@ For each `reveal` in `block.body.custody_key_reveals`, run the following functio ```python def process_custody_key_reveal(state: BeaconState, - reveal: CustodyKeyReveal) -> None: - + reveal: CustodyKeyReveal) -> None: """ Process ``CustodyKeyReveal`` operation. Note that this function mutates ``state``. @@ -377,15 +376,18 @@ def process_custody_key_reveal(state: BeaconState, # Decrement max reveal lateness if response is timely if revealer.next_custody_reveal_period == get_validators_custody_reveal_period(state, reveal.revealer_index) - 2: - revealer.max_reveal_lateness -= MAX_REVEAL_LATENESS_DECREMENT - revealer.max_reveal_lateness = max(revealed_validator.max_reveal_lateness, get_validators_custody_reveal_period(state, reveal.revealed_index) - revealer.next_custody_reveal_period) + revealer.max_reveal_lateness -= MAX_REVEAL_LATENESS_DECREMENT + revealer.max_reveal_lateness = max( + revealer.max_reveal_lateness, + get_validators_custody_reveal_period(state, reveal.revealed_index) - revealer.next_custody_reveal_period + ) # Process reveal revealer.next_custody_reveal_period += 1 # Reward Block Preposer proposer_index = get_beacon_proposer_index(state) - increase_balance(state, proposer_index, base_reward(state, index) // MINOR_REWARD_QUOTIENT) + increase_balance(state, proposer_index, get_base_reward(state, proposer_index) // MINOR_REWARD_QUOTIENT) ``` ##### Early derived secret reveals @@ -396,7 +398,7 @@ For each `reveal` in `block.body.early_derived_secret_reveals`, run the followin ```python def process_early_derived_secret_reveal(state: BeaconState, - reveal: EarlyDerivedSecretReveal) -> None: + reveal: EarlyDerivedSecretReveal) -> None: """ Process ``EarlyDerivedSecretReveal`` operation. Note that this function mutates ``state``. @@ -404,11 +406,12 @@ def process_early_derived_secret_reveal(state: BeaconState, revealed_validator = state.validator_registry[reveal.revealed_index] masker = state.validator_registry[reveal.masker_index] + 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) + EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS assert revealed_validator.slashed is False - assert reveal.revealed_index not in state.exposed_derived_secrets[reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS] + assert reveal.revealed_index not in state.exposed_derived_secrets[derived_secret_location] # Verify signature correctness masker = state.validator_registry[reveal.masker_index] @@ -440,12 +443,16 @@ def process_early_derived_secret_reveal(state: BeaconState, # Calculate penalty max_proposer_slot_reward = ( - get_base_reward(state, reveal.revealed_index) * - SLOTS_PER_EPOCH // - len(get_active_validator_indices(state, get_current_epoch(state))) // - PROPOSER_REWARD_QUOTIENT + get_base_reward(state, reveal.revealed_index) + * SLOTS_PER_EPOCH + // len(get_active_validator_indices(state, get_current_epoch(state))) + // PROPOSER_REWARD_QUOTIENT + ) + penalty = ( + max_proposer_slot_reward + * EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE + * (len(state.exposed_derived_secrets[derived_secret_location]) + 1) ) - penalty = max_proposer_slot_reward * EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE * (len(state.exposed_derived_secrets[reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS]) + 1) # Apply penalty proposer_index = get_beacon_proposer_index(state) @@ -457,8 +464,7 @@ def process_early_derived_secret_reveal(state: BeaconState, decrease_balance(state, reveal.revealed_index, penalty) # Mark this derived secret as exposed so validator cannot be punished repeatedly - state.exposed_derived_secrets[reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS].append(reveal.revealed_index) - + state.exposed_derived_secrets[derived_secret_location].append(reveal.revealed_index) ``` #### Chunk challenges @@ -471,13 +477,13 @@ For each `challenge` in `block.body.custody_chunk_challenges`, run the following def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge) -> None: # Verify the attestation - assert verify_indexed_attestation(state, convert_to_indexed(state, challenge.attestation)) + assert validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation)) # Verify it is not too late to challenge assert slot_to_epoch(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY responder = state.validator_registry[challenge.responder_index] assert responder.exit_epoch >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY # Verify the responder participated in the attestation - attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield) + attesters = get_attesting_indices(state, challenge.attestation.data, challenge.attestation.aggregation_bitfield) assert challenge.responder_index in attesters # Verify the challenge is not a duplicate for record in state.custody_chunk_challenge_records: @@ -526,14 +532,14 @@ def process_bit_challenge(state: BeaconState, assert is_slashable_validator(challenger, get_current_epoch(state)) # Verify the attestation - assert verify_indexed_attestation(state, convert_to_indexed(state, challenge.attestation)) + assert validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation)) # Verify the attestation is eligible for challenging responder = state.validator_registry[challenge.responder_index] assert (slot_to_epoch(challenge.attestation.data.slot) + responder.max_reveal_lateness <= get_validators_custody_reveal_period(state, challenge.responder_index)) # Verify the responder participated in the attestation - attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield) + attesters = get_attesting_indices(state, challenge.attestation.data, challenge.attestation.aggregation_bitfield) assert challenge.responder_index in attesters # A validator can be the challenger or responder for at most one challenge at a time @@ -546,7 +552,7 @@ def process_bit_challenge(state: BeaconState, get_validators_custody_reveal_period( state=state, index=challenge.responder_index, - epoch=slot_to_epoch(attestation.data.slot)), + epoch=slot_to_epoch(challenge.attestation.data.slot)), challenge.responder_index ) assert bls_verify( @@ -564,7 +570,7 @@ def process_bit_challenge(state: BeaconState, chunk_count = get_custody_chunk_count(challenge.attestation) assert verify_bitfield(challenge.chunk_bits, chunk_count) # Verify the first bit of the hash of the chunk bits does not equal the custody bit - custody_bit = get_bitfield_bit(attestation.custody_bitfield, attesters.index(responder_index)) + custody_bit = get_bitfield_bit(challenge.attestation.custody_bitfield, attesters.index(challenge.responder_index)) assert custody_bit != get_bitfield_bit(get_chunk_bits_root(challenge.chunk_bits), 0) # Add new bit challenge record new_record = CustodyBitChallengeRecord( @@ -593,11 +599,13 @@ For each `response` in `block.body.custody_responses`, run the following functio ```python def process_custody_response(state: BeaconState, response: CustodyResponse) -> None: - chunk_challenge = next((record for record in state.custody_chunk_challenge_records if record.challenge_index == response.challenge_index), None) + chunk_challenge = next((record for record in state.custody_chunk_challenge_records + if record.challenge_index == response.challenge_index), None) if chunk_challenge is not None: return process_chunk_challenge_response(state, response, chunk_challenge) - bit_challenge = next((record for record in state.custody_bit_challenge_records if record.challenge_index == response.challenge_index), None) + bit_challenge = next((record for record in state.custody_bit_challenge_records + if record.challenge_index == response.challenge_index), None) if bit_challenge is not None: return process_bit_challenge_response(state, response, bit_challenge) @@ -625,7 +633,7 @@ def process_chunk_challenge_response(state: BeaconState, records[records.index(challenge)] = CustodyChunkChallengeRecord() # Reward the proposer proposer_index = get_beacon_proposer_index(state) - increase_balance(state, proposer_index, base_reward(state, index) // MINOR_REWARD_QUOTIENT) + increase_balance(state, proposer_index, get_base_reward(state, proposer_index) // MINOR_REWARD_QUOTIENT) ``` ```python @@ -651,7 +659,8 @@ def process_bit_challenge_response(state: BeaconState, root=challenge.chunk_bits_merkle_root ) # Verify the chunk bit does not match the challenge chunk bit - assert get_custody_chunk_bit(challenge.responder_key, response.chunk) != get_bitfield_bit(challenge.chunk_bits_leaf, response.chunk_index % 256) + assert (get_custody_chunk_bit(challenge.responder_key, response.chunk) + != get_bitfield_bit(challenge.chunk_bits_leaf, response.chunk_index % 256)) # Clear the challenge records = state.custody_bit_challenge_records records[records.index(challenge)] = CustodyBitChallengeRecord() @@ -670,7 +679,7 @@ def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): if (validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) < - get_validators_custody_reveal_period(state, index)): + get_validators_custody_reveal_period(state, index)): slash_validator(state, index) ``` @@ -712,12 +721,13 @@ def eligible(state: BeaconState, index: ValidatorIndex) -> bool: if len([record for record in state.custody_bit_challenge_records if record.responder_index == index]) > 0: return False # Cannot exit if you have not revealed all of your custody keys - elif validator.next_custody_reveal_period <= get_validators_custody_reveal_period(state, index, validator.exit_epoch): + elif (validator.next_custody_reveal_period + <= get_validators_custody_reveal_period(state, index, validator.exit_epoch)): return False # Cannot exit if you already have elif validator.withdrawable_epoch < FAR_FUTURE_EPOCH: return False # Return minimum time else: - return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS + return get_current_epoch(state) >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY ``` From cfed4bb41ce30fb25b6ae2f36dc3439d4ec24256 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 10:50:07 +0200 Subject: [PATCH 22/55] Adds missing functions --- scripts/build_spec.py | 101 ++++++------------ scripts/function_puller.py | 4 - specs/core/1_custody-game.md | 20 ++-- .../pyspec/eth2spec/utils/minimal_ssz.py | 10 ++ 4 files changed, 50 insertions(+), 85 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index cdcbc2456..f244b91e1 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -5,7 +5,7 @@ from argparse import ArgumentParser from typing import Tuple, List -IMPORTS = '''from typing import ( +PHASE0_IMPORTS = '''from typing import ( Any, Dict, List, @@ -27,6 +27,31 @@ from eth2spec.utils.bls_stub import ( from eth2spec.utils.hash_function import hash ''' +PHASE1_IMPORTS = '''from typing import ( + Any, + Dict, + List, + NewType, + Tuple, +) + +from eth2spec.utils.minimal_ssz import ( + SSZType, + hash_tree_root, + signing_root, + type_of, + empty, +) + +from eth2spec.utils.bls_stub import ( + bls_aggregate_pubkeys, + bls_verify, + bls_verify_multiple, +) + +from eth2spec.utils.hash_function import hash +import math +''' NEW_TYPE_DEFINITIONS = ''' Slot = NewType('Slot', int) # uint64 Epoch = NewType('Epoch', int) # uint64 @@ -82,74 +107,8 @@ def apply_constants_preset(preset: Dict[str, Any]): init_SSZ_types() ''' -def split_and_label(regex_pattern: str, text: str) -> List[str]: - ''' - Splits a string based on regex, but down not remove the matched text. - It subsequently labels the matches with their match - ''' - find_pattern = r'''%s.*?(?=%s|$)''' % (regex_pattern, regex_pattern) - matches = re.findall(find_pattern, text, re.DOTALL) - return list(map(lambda x: [re.match(regex_pattern, x).group(0), x], matches)) - -def inserter(oldfile: str, newfile: str) -> Tuple[str, str]: - ''' - Searches for occurrences of @LabelName in oldfile and replaces them with instances of code wraped as follows: - # begin insert @LabelName - def foo(bar): - return bar - # end insert @LabelName - ''' - new_insert_objects = re.split(r"(# begin insert |# end insert @[\w\d_]*\n)", newfile) - # Retrieve label from insert objects - def get_labeled_object(labeled_text): - label = re.match(r"@[\w\d_]*\n", labeled_text) - if label is not None: - label = label.group(0) - labeled_text = re.sub(label, '', labeled_text) - return {'label': label, 'text': labeled_text} - new_insert_objects = map(get_labeled_object, new_insert_objects) - # Find and replace labels - newfile = "" - for item in new_insert_objects: - if item['label'] is not None: - oldfile, insertions = re.subn('# %s' % item['label'], item['text'], oldfile) - if insertions == 0: - newfile.join('# begin insert %s/n%s# end insert %s' % (item['label'], item['text'], item['label'])) - elif re.match(r"(# begin insert |# end insert )", item['text']) is None: - newfile += item['text'] - return oldfile, newfile - - -def merger(oldfile:str, newfile:str) -> str: - ''' - Seeks out functions and objects in new and old files. - Replaces old objects with new ones if they exist. - ''' - object_regex = r'''(?:\n[@\w]+[\s\w]*[='" "\.\w]*)|(?:\s{4}global_vars\["\w+"\])''' - ssz_object_regex = r'''(?:\w+|\s{4}global_vars\["\w+"\]) = SSZType\(\{\n''' - old_objects = split_and_label(object_regex, oldfile) - new_objects = split_and_label(object_regex, newfile) - for new_item in new_objects: - found_old = False - for index, old_item in enumerate(old_objects): - if old_item[0] == new_item[0]: - ssz_object_match = re.match(ssz_object_regex, new_item[1]) - if ssz_object_match is not None: - new_item[1] = re.sub(ssz_object_regex, '', new_item[1]) - old_item[1] = re.sub(r'\n\w*\}\)', '', old_item[1]) - old_item[1] += new_item[1] - else: - old_item[1] = new_item[1] - found_old = True - old_objects[index] = old_item - break - if not found_old: - old_objects.append(new_item) - return ''.join(elem for elem in map(lambda x: x[1], old_objects)) - - -def objects_to_spec(functions, constants, ssz_objects): +def objects_to_spec(functions, constants, ssz_objects, imports): functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) ssz_objects_instantiation_spec = '\n'.join(map(lambda x: '%s = SSZType(%s)' % (x, ssz_objects[x][:-1]), ssz_objects)) @@ -160,7 +119,7 @@ def objects_to_spec(functions, constants, ssz_objects): + ssz_objects_reinitialization_spec ) return ( - IMPORTS + imports + '\n' + NEW_TYPE_DEFINITIONS + '\n' + constants_spec + '\n' + ssz_objects_instantiation_spec @@ -194,7 +153,7 @@ def combine_ssz_objects(old_objects, new_objects): def build_phase0_spec(sourcefile, outfile=None): functions, constants, ssz_objects = function_puller.get_spec(sourcefile) - spec = objects_to_spec(functions, constants, ssz_objects) + spec = objects_to_spec(functions, constants, ssz_objects, PHASE0_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) @@ -208,7 +167,7 @@ def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): functions = combine_functions(phase0_functions, phase1_functions) constants = combine_constants(phase0_constants, phase1_constants) ssz_objects = combine_functions(phase0_ssz_objects, phase1_ssz_objects) - spec = objects_to_spec(functions, constants, ssz_objects) + spec = objects_to_spec(functions, constants, ssz_objects, PHASE1_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 720f07502..dc0c30998 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -15,7 +15,6 @@ def get_spec(file_name: str): constants = {} ssz_objects = defaultdict(str) function_matcher = re.compile(FUNCTION_REGEX) - # type_defs = [] for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': @@ -26,9 +25,6 @@ def get_spec(file_name: str): elif line[:3] == '```': pulling_from = None else: - # # Handle SSZObjects - # if pulling_from == linenum and line == '{': - # code_lines.append('%s = SSZType({' % current_name) # Handle function definitions if pulling_from is not None: match = function_matcher.match(line) diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index df4f495be..adc121160 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -31,7 +31,7 @@ - [`BeaconState`](#beaconstate) - [`BeaconBlockBody`](#beaconblockbody) - [Helpers](#helpers) - - [`typeof`](#typeof) + - [`type_of`](#type_of) - [`empty`](#empty) - [`get_crosslink_chunk_count`](#get_crosslink_chunk_count) - [`get_custody_chunk_bit`](#get_custody_chunk_bit) @@ -259,13 +259,13 @@ Add the following fields to the end of the specified container objects. Fields w ## Helpers -### `typeof` +### `type_of` -The `typeof` function accepts and SSZ object as a single input and returns the corresponding SSZ type. +The `type_of` function accepts an SSZ object as a single input and returns the corresponding SSZ type. ### `empty` -The `empty` function accepts and SSZ type as input and returns an object of that type with all fields initialized to default values. +The `empty` function accepts an SSZ type as input and returns an object of that type with all fields initialized to default values. ### `get_crosslink_chunk_count` @@ -327,7 +327,7 @@ def get_validators_custody_reveal_period(state: BeaconState, ```python def replace_empty_or_append(list: List[Any], new_element: Any) -> int: for i in range(len(list)): - if list[i] == empty(typeof(new_element)): + if list[i] == empty(type_of(new_element)): list[i] = new_element return i list.append(new_element) @@ -492,7 +492,7 @@ def process_chunk_challenge(state: BeaconState, record.chunk_index != challenge.chunk_index ) # Verify depth - depth = math.log2(next_power_of_two(get_custody_chunk_count(challenge.attestation))) + depth = math.ceil(math.log2(get_custody_chunk_count(challenge.attestation))) assert challenge.chunk_index < 2**depth # Add new chunk challenge record new_record = CustodyChunkChallengeRecord( @@ -580,7 +580,7 @@ def process_bit_challenge(state: BeaconState, deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, data_root=challenge.attestation.data.crosslink.data_root, chunk_count=chunk_count, - chunk_bits_merkle_root=merkle_root(pad_to_power_of_2((challenge.chunk_bits))), + chunk_bits_merkle_root=hash_tree_root(challenge.chunk_bits), responder_key=challenge.responder_key, ) replace_empty_or_append(state.custody_bit_challenge_records, new_record) @@ -646,7 +646,7 @@ def process_bit_challenge_response(state: BeaconState, assert verify_merkle_branch( leaf=hash_tree_root(response.chunk), branch=response.data_branch, - depth=math.log2(next_power_of_two(challenge.chunk_count)), + depth=math.ceil(math.log2(challenge.chunk_count)), index=response.chunk_index, root=challenge.data_root, ) @@ -654,13 +654,13 @@ def process_bit_challenge_response(state: BeaconState, assert verify_merkle_branch( leaf=response.chunk_bits_leaf, branch=response.chunk_bits_branch, - depth=math.log2(next_power_of_two(challenge.chunk_count) // 256), + depth=math.ceil(math.log2(challenge.chunk_count)) >> 8, index=response.chunk_index // 256, root=challenge.chunk_bits_merkle_root ) # Verify the chunk bit does not match the challenge chunk bit assert (get_custody_chunk_bit(challenge.responder_key, response.chunk) - != get_bitfield_bit(challenge.chunk_bits_leaf, response.chunk_index % 256)) + != get_bitfield_bit(challenge.chunk_bits_leaf, response.chunk_index % 256)) # Clear the challenge records = state.custody_bit_challenge_records records[records.index(challenge)] = CustodyBitChallengeRecord() diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index f7784b6de..63516780e 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -58,6 +58,16 @@ class Vector(): return self.length +def type_of(obj): + return obj.__class__ + + +def empty(obj): + for field in obj.fields: + field = get_zero_value(field) + return obj + + def is_basic(typ): # if not a string, it is a complex, and cannot be basic if not isinstance(typ, str): From c954687f583ba5a1b037d5845232447bc8b9eb52 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 11:17:24 +0200 Subject: [PATCH 23/55] Corrects combination of ssz objects --- scripts/build_spec.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index f244b91e1..749dfaee4 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -141,14 +141,16 @@ def combine_constants(old_constants, new_constants): old_constants[key] = value return old_constants + def combine_ssz_objects(old_objects, new_objects): - remove_encasing = lambda x: x[1:-1] - old_objects = map(remove_encasing, old_objects) - new_objects = map(remove_encasing, new_objects) for key, value in new_objects.items(): + # remove leading "{" and trailing "\n}" + old_objects[key] = old_objects[key][1:-3] + # remove leading "{" + value = value[1:] old_objects[key] += value - reapply_encasing = lambda x: '{%s}' %x - return map(reapply_encasing, old_objects) + old_objects[key] = '{' + old_objects[key] + return old_objects def build_phase0_spec(sourcefile, outfile=None): @@ -166,7 +168,7 @@ def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): phase1_functions, phase1_constants, phase1_ssz_objects = function_puller.get_spec(phase1_sourcefile) functions = combine_functions(phase0_functions, phase1_functions) constants = combine_constants(phase0_constants, phase1_constants) - ssz_objects = combine_functions(phase0_ssz_objects, phase1_ssz_objects) + ssz_objects = combine_ssz_objects(phase0_ssz_objects, phase1_ssz_objects) spec = objects_to_spec(functions, constants, ssz_objects, PHASE1_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: From fac9f6c91dbf37e79a84d69a21ff20a80a74ac1d Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 14:00:54 +0200 Subject: [PATCH 24/55] Automatic SSZ dependancy Ordering! --- scripts/build_spec.py | 48 ++++++++++++++++++++++++-------------- scripts/function_puller.py | 9 ++++--- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 749dfaee4..48ef0888c 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -52,17 +52,17 @@ from eth2spec.utils.bls_stub import ( from eth2spec.utils.hash_function import hash import math ''' -NEW_TYPE_DEFINITIONS = ''' -Slot = NewType('Slot', int) # uint64 -Epoch = NewType('Epoch', int) # uint64 -Shard = NewType('Shard', int) # uint64 -ValidatorIndex = NewType('ValidatorIndex', int) # uint64 -Gwei = NewType('Gwei', int) # uint64 -Bytes32 = NewType('Bytes32', bytes) # bytes32 -BLSPubkey = NewType('BLSPubkey', bytes) # bytes48 -BLSSignature = NewType('BLSSignature', bytes) # bytes96 -Store = None -''' +NEW_TYPES = { + 'Slot': 'int', + 'Epoch': 'int', + 'Shard': 'int', + 'ValidatorIndex': 'int', + 'Gwei': 'int', + 'Bytes32': 'bytes', + 'BLSPubkey': 'bytes', + 'BLSSignature': 'bytes', + 'Store': 'None', +} SUNDRY_FUNCTIONS = ''' # Monkey patch validator compute committee code _compute_committee = compute_committee @@ -109,6 +109,7 @@ def apply_constants_preset(preset: Dict[str, Any]): def objects_to_spec(functions, constants, ssz_objects, imports): + new_type_definitions = '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) ssz_objects_instantiation_spec = '\n'.join(map(lambda x: '%s = SSZType(%s)' % (x, ssz_objects[x][:-1]), ssz_objects)) @@ -120,9 +121,9 @@ def objects_to_spec(functions, constants, ssz_objects, imports): ) return ( imports - + '\n' + NEW_TYPE_DEFINITIONS - + '\n' + constants_spec - + '\n' + ssz_objects_instantiation_spec + + '\n' + new_type_definitions + + '\n\n' + constants_spec + + '\n\n' + ssz_objects_instantiation_spec + '\n\n\n' + functions_spec + '\n' + SUNDRY_FUNCTIONS + '\n\n' + ssz_objects_reinitialization_spec @@ -142,14 +143,27 @@ def combine_constants(old_constants, new_constants): return old_constants +def dependency_order_ssz_objects(objects): + items = list(objects.items()) + for key, value in items: + dependencies = re.findall(r'(: [\[]*[A-Z][a-z][\w]+)', value) + dependencies = map(lambda x: re.sub(r'\W', '', x), dependencies) + for dep in dependencies: + if dep in NEW_TYPES: + continue + key_list = list(objects.keys()) + for item in [dep, key] + key_list[key_list.index(dep)+1:]: + objects[item] = objects.pop(item) + + def combine_ssz_objects(old_objects, new_objects): for key, value in new_objects.items(): # remove leading "{" and trailing "\n}" - old_objects[key] = old_objects[key][1:-3] + old_objects[key] = old_objects.get(key, '')[1:-3] # remove leading "{" value = value[1:] - old_objects[key] += value - old_objects[key] = '{' + old_objects[key] + old_objects[key] = '{' + old_objects.get(key, '') + value + dependency_order_ssz_objects(old_objects) return old_objects diff --git a/scripts/function_puller.py b/scripts/function_puller.py index dc0c30998..29ecccfbf 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -1,7 +1,6 @@ import sys import re from typing import List -from collections import defaultdict FUNCTION_REGEX = r'^def [\w_]*' @@ -11,9 +10,9 @@ def get_spec(file_name: str): code_lines = [] pulling_from = None # line number of start of latest object current_name = None # most recent section title - functions = defaultdict(str) + functions = {} constants = {} - ssz_objects = defaultdict(str) + ssz_objects = {} function_matcher = re.compile(FUNCTION_REGEX) for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() @@ -31,9 +30,9 @@ def get_spec(file_name: str): if match is not None: current_name = match.group(0) if function_matcher.match(current_name) is None: - ssz_objects[current_name] += line + '\n' + ssz_objects[current_name] = ssz_objects.get(current_name, '') + line + '\n' else: - functions[current_name] += line + '\n' + functions[current_name] = functions.get(current_name, '') + line + '\n' # Handle constant table entries elif pulling_from is None and len(line) > 0 and line[0] == '|': row = line[1:].split('|') From b68c471a54ee41ade662efaca1102f364a44c503 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 17:08:03 +0200 Subject: [PATCH 25/55] Moves spec to global variable --- .../test_process_attestation.py | 42 +++++++++---------- .../test_process_attester_slashing.py | 26 ++++++------ .../test_process_block_header.py | 22 +++++----- .../block_processing/test_process_deposit.py | 8 ++-- .../test_process_proposer_slashing.py | 22 +++++----- .../block_processing/test_process_transfer.py | 34 +++++++-------- .../block_processing/test_voluntary_exit.py | 24 +++++------ test_libs/pyspec/tests/phase0/conftest.py | 23 ++++------ .../test_process_crosslinks.py | 18 ++++---- .../test_process_registry_updates.py | 4 +- .../pyspec/tests/phase0/test_finality.py | 30 ++++++------- test_libs/pyspec/tests/phase0/test_sanity.py | 30 ++++++------- ...est_process_early_derived_secret_reveal.py | 36 ++++++++-------- test_libs/pyspec/tests/phase1/conftest.py | 20 ++++----- 14 files changed, 163 insertions(+), 176 deletions(-) diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py index 5dcf17e38..faa954d53 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.attestations -def run_attestation_processing(spec, helpers, state, attestation, valid=True): +def run_attestation_processing(state, attestation, valid=True): """ Run ``spec.process_attestation`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -29,81 +29,81 @@ def run_attestation_processing(spec, helpers, state, attestation, valid=True): return state, post_state -def test_success(spec, helpers, state): +def test_success(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) + pre_state, post_state = run_attestation_processing(state, attestation) return pre_state, attestation, post_state -def test_success_prevous_epoch(spec, helpers, state): +def test_success_prevous_epoch(state): attestation = helpers.get_valid_attestation(state) block = helpers.build_empty_block_for_next_slot(state) block.slot = state.slot + spec.SLOTS_PER_EPOCH spec.state_transition(state, block) - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) + pre_state, post_state = run_attestation_processing(state, attestation) return pre_state, attestation, post_state -def test_before_inclusion_delay(spec, helpers, state): +def test_before_inclusion_delay(state): attestation = helpers.get_valid_attestation(state) # do not increment slot to allow for inclusion delay - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_after_epoch_slots(spec, helpers, state): +def test_after_epoch_slots(state): attestation = helpers.get_valid_attestation(state) block = helpers.build_empty_block_for_next_slot(state) # increment past latest inclusion slot block.slot = state.slot + spec.SLOTS_PER_EPOCH + 1 spec.state_transition(state, block) - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_bad_source_epoch(spec, helpers, state): +def test_bad_source_epoch(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.source_epoch += 10 - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_bad_source_root(spec, helpers, state): +def test_bad_source_root(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.source_root = b'\x42' * 32 - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_non_zero_crosslink_data_root(spec, helpers, state): +def test_non_zero_crosslink_data_root(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.crosslink.data_root = b'\x42' * 32 - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_bad_previous_crosslink(spec, helpers, state): +def test_bad_previous_crosslink(state): helpers.next_epoch(state) attestation = helpers.get_valid_attestation(state) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): @@ -111,28 +111,28 @@ def test_bad_previous_crosslink(spec, helpers, state): state.current_crosslinks[attestation.data.crosslink.shard].epoch += 10 - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_non_empty_custody_bitfield(spec, helpers, state): +def test_non_empty_custody_bitfield(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation, False) + pre_state, post_state = run_attestation_processing(state, attestation, False) return pre_state, attestation, post_state -def test_empty_aggregation_bitfield(spec, helpers, state): +def test_empty_aggregation_bitfield(state): attestation = helpers.get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.aggregation_bitfield = b'\x00' * len(attestation.aggregation_bitfield) - pre_state, post_state = run_attestation_processing(spec, helpers, state, attestation) + pre_state, post_state = run_attestation_processing(state, attestation) return pre_state, attestation, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py index ed48b17cf..66617fd6d 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.attester_slashings -def run_attester_slashing_processing(spec, helpers, state, attester_slashing, valid=True): +def run_attester_slashing_processing(state, attester_slashing, valid=True): """ Run ``spec.process_attester_slashing`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -40,15 +40,15 @@ def run_attester_slashing_processing(spec, helpers, state, attester_slashing, va return state, post_state -def test_success_double(spec, helpers, state): +def test_success_double(state): attester_slashing = helpers.get_valid_attester_slashing(state) - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) return pre_state, attester_slashing, post_state -def test_success_surround(spec, helpers, state): +def test_success_surround(state): helpers.next_epoch(state) state.current_justified_epoch += 1 attester_slashing = helpers.get_valid_attester_slashing(state) @@ -57,32 +57,32 @@ def test_success_surround(spec, helpers, state): attester_slashing.attestation_1.data.source_epoch = attester_slashing.attestation_2.data.source_epoch - 1 attester_slashing.attestation_1.data.target_epoch = attester_slashing.attestation_2.data.target_epoch + 1 - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) return pre_state, attester_slashing, post_state -def test_same_data(spec, helpers, state): +def test_same_data(state): attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.data = attester_slashing.attestation_2.data - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_no_double_or_surround(spec, helpers, state): +def test_no_double_or_surround(state): attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.data.target_epoch += 1 - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_participants_already_slashed(spec, helpers, state): +def test_participants_already_slashed(state): attester_slashing = helpers.get_valid_attester_slashing(state) # set all indices to slashed @@ -91,17 +91,17 @@ def test_participants_already_slashed(spec, helpers, state): for index in validator_indices: state.validator_registry[index].slashed = True - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) return pre_state, attester_slashing, post_state -def test_custody_bit_0_and_1(spec, helpers, state): +def test_custody_bit_0_and_1(state): attester_slashing = helpers.get_valid_attester_slashing(state) attester_slashing.attestation_1.custody_bit_1_indices = ( attester_slashing.attestation_1.custody_bit_0_indices ) - pre_state, post_state = run_attester_slashing_processing(spec, helpers, state, attester_slashing, False) + pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) return pre_state, attester_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py index e4cd70f77..f7032a283 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py @@ -6,17 +6,17 @@ import pytest pytestmark = pytest.mark.header -def prepare_state_for_header_processing(spec, helpers, state): +def prepare_state_for_header_processing(state): spec.process_slot(state) helpers.advance_slot(state) -def run_block_header_processing(spec, helpers, state, block, valid=True): +def run_block_header_processing(state, block, valid=True): """ Run ``spec.process_block_header`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` """ - prepare_state_for_header_processing(spec, helpers, state) + prepare_state_for_header_processing(state) post_state = deepcopy(state) if not valid: @@ -28,29 +28,29 @@ def run_block_header_processing(spec, helpers, state, block, valid=True): return state, post_state -def test_success(spec, helpers, state): +def test_success(state): block = helpers.build_empty_block_for_next_slot(state) - pre_state, post_state = run_block_header_processing(spec, helpers, state, block) + pre_state, post_state = run_block_header_processing(state, block) return state, block, post_state -def test_invalid_slot(spec, helpers, state): +def test_invalid_slot(state): block = helpers.build_empty_block_for_next_slot(state) block.slot = state.slot + 2 # invalid slot - pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) + pre_state, post_state = run_block_header_processing(state, block, valid=False) return pre_state, block, None -def test_invalid_parent_block_root(spec, helpers, state): +def test_invalid_parent_block_root(state): block = helpers.build_empty_block_for_next_slot(state) block.parent_root = b'\12' * 32 # invalid prev root - pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) + pre_state, post_state = run_block_header_processing(state, block, valid=False) return pre_state, block, None -def test_proposer_slashed(spec, helpers, state): +def test_proposer_slashed(state): # use stub state to get proposer index of next slot stub_state = deepcopy(state) helpers.next_slot(stub_state) @@ -61,5 +61,5 @@ def test_proposer_slashed(spec, helpers, state): block = helpers.build_empty_block_for_next_slot(state) - pre_state, post_state = run_block_header_processing(spec, helpers, state, block, valid=False) + pre_state, post_state = run_block_header_processing(state, block, valid=False) return pre_state, block, None diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py index 97d49114b..f3abab354 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.deposits -def test_success(spec, helpers, state): +def test_success(state): pre_state = deepcopy(state) # fill previous deposits with zero-hash deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) @@ -38,7 +38,7 @@ def test_success(spec, helpers, state): return pre_state, deposit, post_state -def test_success_top_up(spec, helpers, state): +def test_success_top_up(state): pre_state = deepcopy(state) deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) @@ -70,7 +70,7 @@ def test_success_top_up(spec, helpers, state): return pre_state, deposit, post_state -def test_wrong_index(spec, helpers, state): +def test_wrong_index(state): pre_state = deepcopy(state) deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) @@ -99,7 +99,7 @@ def test_wrong_index(spec, helpers, state): return pre_state, deposit, None -def test_bad_merkle_proof(spec, helpers, state): +def test_bad_merkle_proof(state): pre_state = deepcopy(state) deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py index 6f82d6c33..f97eb1584 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.proposer_slashings -def run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, valid=True): +def run_proposer_slashing_processing(state, proposer_slashing, valid=True): """ Run ``spec.process_proposer_slashing`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -33,48 +33,48 @@ def run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, va return state, post_state -def test_success(spec, helpers, state): +def test_success(state): proposer_slashing = helpers.get_valid_proposer_slashing(state) - pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing) + pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing) return pre_state, proposer_slashing, post_state -def test_epochs_are_different(spec, helpers, state): +def test_epochs_are_different(state): proposer_slashing = helpers.get_valid_proposer_slashing(state) # set slots to be in different epochs proposer_slashing.header_2.slot += spec.SLOTS_PER_EPOCH - pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_headers_are_same(spec, helpers, state): +def test_headers_are_same(state): proposer_slashing = helpers.get_valid_proposer_slashing(state) # set headers to be the same proposer_slashing.header_2 = proposer_slashing.header_1 - pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_proposer_is_slashed(spec, helpers, state): +def test_proposer_is_slashed(state): proposer_slashing = helpers.get_valid_proposer_slashing(state) # set proposer to slashed state.validator_registry[proposer_slashing.proposer_index].slashed = True - pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) return pre_state, proposer_slashing, post_state -def test_proposer_is_withdrawn(spec, helpers, state): +def test_proposer_is_withdrawn(state): proposer_slashing = helpers.get_valid_proposer_slashing(state) # set proposer withdrawable_epoch in past @@ -82,6 +82,6 @@ def test_proposer_is_withdrawn(spec, helpers, state): proposer_index = proposer_slashing.proposer_index state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1 - pre_state, post_state = run_proposer_slashing_processing(spec, helpers, state, proposer_slashing, False) + pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) return pre_state, proposer_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py index 197898ec0..724c69647 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.transfers -def run_transfer_processing(spec, helpers, state, transfer, valid=True): +def run_transfer_processing(state, transfer, valid=True): """ Run ``spec.process_transfer`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -34,17 +34,17 @@ def run_transfer_processing(spec, helpers, state, transfer, valid=True): return state, post_state -def test_success_non_activated(spec, helpers, state): +def test_success_non_activated(state): transfer = helpers.get_valid_transfer(state) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) + pre_state, post_state = run_transfer_processing(state, transfer) return pre_state, transfer, post_state -def test_success_withdrawable(spec, helpers, state): +def test_success_withdrawable(state): helpers.next_epoch(state) transfer = helpers.get_valid_transfer(state) @@ -52,44 +52,44 @@ def test_success_withdrawable(spec, helpers, state): # withdrawable_epoch in past so can transfer state.validator_registry[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1 - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) + pre_state, post_state = run_transfer_processing(state, transfer) return pre_state, transfer, post_state -def test_success_active_above_max_effective(spec, helpers, state): +def test_success_active_above_max_effective(state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE // 32 state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + amount transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer) + pre_state, post_state = run_transfer_processing(state, transfer) return pre_state, transfer, post_state -def test_active_but_transfer_past_effective_balance(spec, helpers, state): +def test_active_but_transfer_past_effective_balance(state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE // 32 state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) + pre_state, post_state = run_transfer_processing(state, transfer, False) return pre_state, transfer, post_state -def test_incorrect_slot(spec, helpers, state): +def test_incorrect_slot(state): transfer = helpers.get_valid_transfer(state, slot=state.slot+1) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) + pre_state, post_state = run_transfer_processing(state, transfer, False) return pre_state, transfer, post_state -def test_insufficient_balance(spec, helpers, state): +def test_insufficient_balance(state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] amount = spec.MAX_EFFECTIVE_BALANCE state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE @@ -98,12 +98,12 @@ def test_insufficient_balance(spec, helpers, state): # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) + pre_state, post_state = run_transfer_processing(state, transfer, False) return pre_state, transfer, post_state -def test_no_dust(spec, helpers, state): +def test_no_dust(state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] balance = state.balances[sender_index] transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, fee=0) @@ -111,18 +111,18 @@ def test_no_dust(spec, helpers, state): # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) + pre_state, post_state = run_transfer_processing(state, transfer, False) return pre_state, transfer, post_state -def test_invalid_pubkey(spec, helpers, state): +def test_invalid_pubkey(state): transfer = helpers.get_valid_transfer(state) state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - pre_state, post_state = run_transfer_processing(spec, helpers, state, transfer, False) + pre_state, post_state = run_transfer_processing(state, transfer, False) return pre_state, transfer, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py index d9e643b55..a3e54f00e 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.voluntary_exits -def run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, valid=True): +def run_voluntary_exit_processing(state, voluntary_exit, valid=True): """ Run ``spec.process_voluntary_exit`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -27,7 +27,7 @@ def run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, valid=Tr return state, post_state -def test_success(spec, helpers, state): +def test_success(state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -42,11 +42,11 @@ def test_success(spec, helpers, state): privkey, ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit) return pre_state, voluntary_exit, post_state -def test_success_exit_queue(spec, helpers, state): +def test_success_exit_queue(state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -64,7 +64,7 @@ def test_success_exit_queue(spec, helpers, state): privkey, ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, post_state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) # exit an additional validator validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] @@ -76,7 +76,7 @@ def test_success_exit_queue(spec, helpers, state): privkey, ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, post_state, voluntary_exit) + pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) assert ( post_state.validator_registry[validator_index].exit_epoch == @@ -86,7 +86,7 @@ def test_success_exit_queue(spec, helpers, state): return pre_state, voluntary_exit, post_state -def test_validator_not_active(spec, helpers, state): +def test_validator_not_active(state): current_epoch = spec.get_current_epoch(state) validator_index = spec.get_active_validator_indices(state, current_epoch)[0] privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] @@ -103,11 +103,11 @@ def test_validator_not_active(spec, helpers, state): privkey, ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) return pre_state, voluntary_exit, post_state -def test_validator_already_exited(spec, helpers, state): +def test_validator_already_exited(state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH @@ -125,11 +125,11 @@ def test_validator_already_exited(spec, helpers, state): privkey, ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) return pre_state, voluntary_exit, post_state -def test_validator_not_active_long_enough(spec, helpers, state): +def test_validator_not_active_long_enough(state): current_epoch = spec.get_current_epoch(state) validator_index = spec.get_active_validator_indices(state, current_epoch)[0] privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] @@ -146,5 +146,5 @@ def test_validator_not_active_long_enough(spec, helpers, state): spec.PERSISTENT_COMMITTEE_PERIOD ) - pre_state, post_state = run_voluntary_exit_processing(spec, helpers, state, voluntary_exit, False) + pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) return pre_state, voluntary_exit, post_state diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index 25b540aa0..4db8f3919 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -1,10 +1,10 @@ import pytest -from eth2spec.phase0 import spec as _spec +from eth2spec.phase0 import spec from preset_loader import loader -from tests.phase0 import helpers as _helpers - +from tests.phase0 import helpers +from tests.phase0 import test_finality def pytest_addoption(parser): parser.addoption( @@ -13,13 +13,15 @@ def pytest_addoption(parser): @pytest.fixture(autouse=True) def config(request): + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) - _spec.apply_constants_preset(presets) + spec.apply_constants_preset(presets) @pytest.fixture def num_validators(config): - return _spec.SLOTS_PER_EPOCH * 8 + return spec.SLOTS_PER_EPOCH * 8 @pytest.fixture def deposit_data_leaves(): @@ -27,13 +29,4 @@ def deposit_data_leaves(): @pytest.fixture def state(num_validators, deposit_data_leaves): - return _helpers.create_genesis_state(num_validators, deposit_data_leaves) - -@pytest.fixture -def spec(): - return _spec - -@pytest.fixture -def helpers(): - return _helpers - + return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index 6e4ad2dd6..a3ec38989 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.crosslinks -def run_process_crosslinks(spec, helpers, state, valid=True): +def run_process_crosslinks(state, valid=True): # transition state to slot before state transition slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 block = helpers.build_empty_block_for_next_slot(state) @@ -22,8 +22,8 @@ def run_process_crosslinks(spec, helpers, state, valid=True): return state, post_state -def test_no_attestations(spec, helpers, state): - pre_state, post_state = run_process_crosslinks(spec, helpers, state) +def test_no_attestations(state): + pre_state, post_state = run_process_crosslinks(state) for shard in range(spec.SHARD_COUNT): assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] @@ -31,7 +31,7 @@ def test_no_attestations(spec, helpers, state): return pre_state, post_state -def test_single_crosslink_update_from_current_epoch(spec, helpers, state): +def test_single_crosslink_update_from_current_epoch(state): helpers.next_epoch(state) attestation = helpers.get_valid_attestation(state) @@ -41,7 +41,7 @@ def test_single_crosslink_update_from_current_epoch(spec, helpers, state): assert len(state.current_epoch_attestations) == 1 - pre_state, post_state = run_process_crosslinks(spec, helpers, state) + pre_state, post_state = run_process_crosslinks(state) shard = attestation.data.crosslink.shard assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] @@ -50,7 +50,7 @@ def test_single_crosslink_update_from_current_epoch(spec, helpers, state): return pre_state, post_state -def test_single_crosslink_update_from_previous_epoch(spec, helpers, state): +def test_single_crosslink_update_from_previous_epoch(state): helpers.next_epoch(state) attestation = helpers.get_valid_attestation(state) @@ -60,7 +60,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, helpers, state): assert len(state.previous_epoch_attestations) == 1 - pre_state, post_state = run_process_crosslinks(spec, helpers, state) + pre_state, post_state = run_process_crosslinks(state) crosslink_deltas = spec.get_crosslink_deltas(state) shard = attestation.data.crosslink.shard @@ -74,7 +74,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, helpers, state): return pre_state, post_state -def test_double_late_crosslink(spec, helpers, state): +def test_double_late_crosslink(state): helpers.next_epoch(state) state.slot += 4 @@ -100,7 +100,7 @@ def test_double_late_crosslink(spec, helpers, state): assert len(state.previous_epoch_attestations) == 1 assert len(state.current_epoch_attestations) == 0 - pre_state, post_state = run_process_crosslinks(spec, helpers, state) + pre_state, post_state = run_process_crosslinks(state) crosslink_deltas = spec.get_crosslink_deltas(state) shard = attestation_2.data.crosslink.shard diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py index 8b5ebf9b4..962ad6704 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py @@ -6,7 +6,7 @@ import pytest pytestmark = pytest.mark.state -def test_activation(spec, helpers, state): +def test_activation(state): index = 0 assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) @@ -33,7 +33,7 @@ def test_activation(spec, helpers, state): return pre_state, blocks, state -def test_ejection(spec, helpers, state): +def test_ejection(state): index = 0 assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH diff --git a/test_libs/pyspec/tests/phase0/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py index e30e125f9..be8ecaa1d 100644 --- a/test_libs/pyspec/tests/phase0/test_finality.py +++ b/test_libs/pyspec/tests/phase0/test_finality.py @@ -33,7 +33,7 @@ def check_finality(state, assert state.finalized_root == prev_state.finalized_root -def next_epoch_with_attestations(spec, helpers, state, +def next_epoch_with_attestations(state, fill_cur_epoch, fill_prev_epoch): post_state = deepcopy(state) @@ -59,12 +59,12 @@ def next_epoch_with_attestations(spec, helpers, state, return state, blocks, post_state -def test_finality_rule_4(spec, helpers, state): +def test_finality_rule_4(state): test_state = deepcopy(state) blocks = [] for epoch in range(4): - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) blocks += new_blocks # justification/finalization skipped at GENESIS_EPOCH @@ -84,7 +84,7 @@ def test_finality_rule_4(spec, helpers, state): return state, blocks, test_state -def test_finality_rule_1(spec, helpers, state): +def test_finality_rule_1(state): # get past first two epochs that finality does not run on helpers.next_epoch(state) helpers.next_epoch(state) @@ -94,7 +94,7 @@ def test_finality_rule_1(spec, helpers, state): blocks = [] for epoch in range(3): - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) blocks += new_blocks if epoch == 0: @@ -110,7 +110,7 @@ def test_finality_rule_1(spec, helpers, state): return pre_state, blocks, test_state -def test_finality_rule_2(spec, helpers, state): +def test_finality_rule_2(state): # get past first two epochs that finality does not run on helpers.next_epoch(state) helpers.next_epoch(state) @@ -121,13 +121,13 @@ def test_finality_rule_2(spec, helpers, state): blocks = [] for epoch in range(3): if epoch == 0: - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) check_finality(test_state, prev_state, True, False, False) elif epoch == 1: - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, False) check_finality(test_state, prev_state, False, True, False) elif epoch == 2: - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) # finalized by rule 2 check_finality(test_state, prev_state, True, False, True) assert test_state.finalized_epoch == prev_state.previous_justified_epoch @@ -138,7 +138,7 @@ def test_finality_rule_2(spec, helpers, state): return pre_state, blocks, test_state -def test_finality_rule_3(spec, helpers, state): +def test_finality_rule_3(state): """ Test scenario described here https://github.com/ethereum/eth2.0-specs/issues/611#issuecomment-463612892 @@ -152,29 +152,29 @@ def test_finality_rule_3(spec, helpers, state): test_state = deepcopy(state) blocks = [] - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) blocks += new_blocks check_finality(test_state, prev_state, True, False, False) # In epoch N, JE is set to N, prev JE is set to N-1 - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, False) blocks += new_blocks check_finality(test_state, prev_state, True, True, True) # In epoch N+1, JE is N, prev JE is N-1, and not enough messages get in to do anything - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, False) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, False) blocks += new_blocks check_finality(test_state, prev_state, False, True, False) # In epoch N+2, JE is N, prev JE is N, and enough messages from the previous epoch get in to justify N+1. # N+1 now becomes the JE. Not enough messages from epoch N+2 itself get in to justify N+2 - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, False, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, False, True) blocks += new_blocks # rule 2 check_finality(test_state, prev_state, True, False, True) # In epoch N+3, LJE is N+1, prev LJE is N, and enough messages get in to justify epochs N+2 and N+3. - prev_state, new_blocks, test_state = next_epoch_with_attestations(spec, helpers, test_state, True, True) + prev_state, new_blocks, test_state = next_epoch_with_attestations(test_state, True, True) blocks += new_blocks # rule 3 check_finality(test_state, prev_state, True, True, True) diff --git a/test_libs/pyspec/tests/phase0/test_sanity.py b/test_libs/pyspec/tests/phase0/test_sanity.py index ad206881d..821d97386 100644 --- a/test_libs/pyspec/tests/phase0/test_sanity.py +++ b/test_libs/pyspec/tests/phase0/test_sanity.py @@ -17,7 +17,7 @@ from eth2spec.utils.merkle_minimal import ( pytestmark = pytest.mark.sanity -def test_slot_transition(spec, helpers, state): +def test_slot_transition(state): test_state = deepcopy(state) spec.process_slot(test_state) helpers.advance_slot(test_state) @@ -26,7 +26,7 @@ def test_slot_transition(spec, helpers, state): return test_state -def test_empty_block_transition(spec, helpers, state): +def test_empty_block_transition(state): test_state = deepcopy(state) block = helpers.build_empty_block_for_next_slot(test_state) @@ -38,7 +38,7 @@ def test_empty_block_transition(spec, helpers, state): return state, [block], test_state -def test_skipped_slots(spec, helpers, state): +def test_skipped_slots(state): test_state = deepcopy(state) block = helpers.build_empty_block_for_next_slot(test_state) block.slot += 3 @@ -52,7 +52,7 @@ def test_skipped_slots(spec, helpers, state): return state, [block], test_state -def test_empty_epoch_transition(spec, helpers, state): +def test_empty_epoch_transition(state): test_state = deepcopy(state) block = helpers.build_empty_block_for_next_slot(test_state) block.slot += spec.SLOTS_PER_EPOCH @@ -66,7 +66,7 @@ def test_empty_epoch_transition(spec, helpers, state): return state, [block], test_state -def test_empty_epoch_transition_not_finalizing(spec, helpers, state): +def test_empty_epoch_transition_not_finalizing(state): test_state = deepcopy(state) block = helpers.build_empty_block_for_next_slot(test_state) block.slot += spec.SLOTS_PER_EPOCH * 5 @@ -81,7 +81,7 @@ def test_empty_epoch_transition_not_finalizing(spec, helpers, state): return state, [block], test_state -def test_proposer_slashing(spec, helpers, state): +def test_proposer_slashing(state): test_state = deepcopy(state) proposer_slashing = helpers.get_valid_proposer_slashing(state) validator_index = proposer_slashing.proposer_index @@ -105,7 +105,7 @@ def test_proposer_slashing(spec, helpers, state): return state, [block], test_state -def test_attester_slashing(spec, helpers, state): +def test_attester_slashing(state): test_state = deepcopy(state) attester_slashing = helpers.get_valid_attester_slashing(state) validator_index = attester_slashing.attestation_1.custody_bit_0_indices[0] @@ -136,7 +136,7 @@ def test_attester_slashing(spec, helpers, state): return state, [block], test_state -def test_deposit_in_block(spec, helpers, state): +def test_deposit_in_block(state): pre_state = deepcopy(state) test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) @@ -173,7 +173,7 @@ def test_deposit_in_block(spec, helpers, state): return pre_state, [block], post_state -def test_deposit_top_up(spec, helpers, state): +def test_deposit_top_up(state): pre_state = deepcopy(state) test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) @@ -212,7 +212,7 @@ def test_deposit_top_up(spec, helpers, state): return pre_state, [block], post_state -def test_attestation(spec, helpers, state): +def test_attestation(state): state.slot = spec.SLOTS_PER_EPOCH test_state = deepcopy(state) attestation = helpers.get_valid_attestation(state) @@ -243,7 +243,7 @@ def test_attestation(spec, helpers, state): return state, [attestation_block, epoch_block], test_state -def test_voluntary_exit(spec, helpers, state): +def test_voluntary_exit(state): pre_state = deepcopy(state) validator_index = spec.get_active_validator_indices( pre_state, @@ -289,7 +289,7 @@ def test_voluntary_exit(spec, helpers, state): return pre_state, [initiate_exit_block, exit_block], post_state -def test_transfer(spec, helpers, state): +def test_transfer(state): # overwrite default 0 to test spec.apply_constants_preset({"MAX_TRANSFERS": 1}) @@ -341,7 +341,7 @@ def test_transfer(spec, helpers, state): return pre_state, [block], post_state -def test_balance_driven_status_transitions(spec, helpers, state): +def test_balance_driven_status_transitions(state): current_epoch = spec.get_current_epoch(state) validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] @@ -363,7 +363,7 @@ def test_balance_driven_status_transitions(spec, helpers, state): return state, [block], post_state -def test_historical_batch(spec, helpers, state): +def test_historical_batch(state): state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1 post_state = deepcopy(state) @@ -379,7 +379,7 @@ def test_historical_batch(spec, helpers, state): return state, [block], post_state -def test_eth1_data_votes(spec, helpers, state): +def test_eth1_data_votes(state): post_state = deepcopy(state) expected_votes = 0 diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index e3cf30ef3..08f7cf9ac 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -4,7 +4,7 @@ import pytest #mark entire file as 'randao_key_reveals' pytestmark = pytest.mark.randao_key_reveals -def terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, valid=True): +def terun_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): """ Run ``process_randao_key_reveal`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -34,63 +34,63 @@ def terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_ke return state, post_state -def test_success(spec, helpers, state): +def test_success(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal) return pre_state, randao_key_reveal, post_state -def test_reveal_from_current_epoch(spec, helpers, state): +def test_reveal_from_current_epoch(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state @pytest.mark.skip(reason="Not currently possible as we are testing at epoch 0") -def test_reveal_from_past_epoch(spec, helpers, state): +def test_reveal_from_past_epoch(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) - 1) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state -def test_reveal_with_custody_padding(spec, helpers, state): +def test_reveal_with_custody_padding(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, True) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state -def test_reveal_with_custody_padding_minus_one(spec, helpers, state): +def test_reveal_with_custody_padding_minus_one(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, True) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state -def test_double_reveal(spec, helpers, state): +def test_double_reveal(state): randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1) - pre_state, intermediate_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal1) + pre_state, intermediate_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal1) randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal(intermediate_state, spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1) - _, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, intermediate_state, randao_key_reveal2, False) + _, post_state = terun_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state -def test_revealer_is_slashed(spec, helpers, state): +def test_revealer_is_slashed(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) state.validator_registry[randao_key_reveal.revealed_index].slashed = True - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state -def test_far_future_epoch(spec, helpers, state): +def test_far_future_epoch(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) - pre_state, post_state = terun_early_derived_secret_reveal_processing(spec, helpers, state, randao_key_reveal, False) + pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 4af3451a5..62dd2be38 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -1,9 +1,9 @@ import pytest -from eth2spec.phase1 import spec as _spec +from eth2spec.phase1 import spec from preset_loader import loader -from tests.phase1 import helpers as _helpers +from tests.phase1 import helpers as helpers from tests.phase0.conftest import ( pytest_addoption, @@ -13,23 +13,17 @@ from tests.phase0.conftest import ( # This is redfined so that the constants are re-applied @pytest.fixture(autouse=True) def config(request): + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) - _spec.apply_constants_preset(presets) + spec.apply_constants_preset(presets) @pytest.fixture def num_validators(config): - return _spec.SLOTS_PER_EPOCH * 8 + return spec.SLOTS_PER_EPOCH * 8 #This is redefined so that the BeaconState is the new SSZ Object @pytest.fixture def state(num_validators, deposit_data_leaves): - return _helpers.create_genesis_state(num_validators, deposit_data_leaves) - -@pytest.fixture -def spec(): - return _spec - -@pytest.fixture -def helpers(): - return _helpers + return helpers.create_genesis_state(num_validators, deposit_data_leaves) From 65b0701f8c68ef9416a5ebbb889c04c0de52fd73 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 20 May 2019 18:14:37 +0200 Subject: [PATCH 26/55] Helpers depend on spec version and p1 tests work --- Makefile | 2 +- test_libs/pyspec/tests/phase0/conftest.py | 5 +- .../test_process_crosslinks.py | 4 +- test_libs/pyspec/tests/phase0/helpers.py | 148 +++++++----------- .../pyspec/tests/phase0/test_finality.py | 2 +- test_libs/pyspec/tests/phase1/conftest.py | 18 ++- test_libs/pyspec/tests/phase1/helpers.py | 31 ++-- 7 files changed, 83 insertions(+), 127 deletions(-) diff --git a/Makefile b/Makefile index a262ac5e1..f8682734d 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ PY_SPEC_PHASE_1_DEPS = $(SPEC_DIR)/core/1_*.md PY_SPEC_ALL_TARGETS = $(PY_SPEC_PHASE_0_TARGETS) $(PY_SPEC_PHASE_1_TARGETS) -.PHONY: clean all test citest gen_yaml_tests pyspec phase0 install_test +.PHONY: clean all test citest gen_yaml_tests pyspec phase0 phase1 install_test all: $(PY_SPEC_ALL_TARGETS) $(YAML_TEST_DIR) $(YAML_TEST_TARGETS) diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index 4db8f3919..0549a1422 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -13,11 +13,12 @@ def pytest_addoption(parser): @pytest.fixture(autouse=True) def config(request): - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) spec.apply_constants_preset(presets) + helpers.spec = spec + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers @pytest.fixture def num_validators(config): diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index a3ec38989..19c668e74 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -67,7 +67,7 @@ def test_single_crosslink_update_from_previous_epoch(state): assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard] # ensure rewarded - for index in helpers.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): + for index in spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[1][index] == 0 @@ -108,7 +108,7 @@ def test_double_late_crosslink(state): # ensure that the current crosslinks were not updated by the second attestation assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink - for index in helpers.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): + for index in spec.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/phase0/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py index e8b4f789e..82851c1cc 100644 --- a/test_libs/pyspec/tests/phase0/helpers.py +++ b/test_libs/pyspec/tests/phase0/helpers.py @@ -2,58 +2,18 @@ from copy import deepcopy from py_ecc import bls -import eth2spec.phase0.spec as spec - from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.phase0.spec import ( - # constants - ZERO_HASH, - MAX_EPOCHS_PER_CROSSLINK, - # SSZ - Attestation, - AttestationData, - AttestationDataAndCustodyBit, - AttesterSlashing, - BeaconBlock, - BeaconBlockHeader, - Crosslink, - Deposit, - DepositData, - Eth1Data, - ProposerSlashing, - Transfer, - VoluntaryExit, - # functions - convert_to_indexed, - get_active_validator_indices, - get_attesting_indices, - get_block_root, - get_block_root_at_slot, - get_crosslink_committee, - get_current_epoch, - get_domain, - get_epoch_start_slot, - get_genesis_beacon_state, - get_previous_epoch, - get_shard_delta, - hash_tree_root, - slot_to_epoch, - state_transition, - verify_merkle_branch, - hash, -) + from eth2spec.utils.merkle_minimal import ( calc_merkle_tree_from_leaves, get_merkle_proof, get_merkle_root, ) - privkeys = [i + 1 for i in range(1024)] pubkeys = [bls.privtopub(privkey) for privkey in privkeys] pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} - def advance_slot(state) -> None: state.slot += 1 @@ -83,10 +43,10 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=N deposit_data_list = [] for i in range(num_validators): pubkey = pubkeys[i] - deposit_data = DepositData( + deposit_data = spec.DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], + withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], amount=spec.MAX_EFFECTIVE_BALANCE, signature=signature, ) @@ -95,12 +55,12 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=N tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) root = get_merkle_root((tuple(deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=i)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) deposit_data_list.append(deposit_data) genesis_validator_deposits = [] for i in range(num_validators): - genesis_validator_deposits.append(Deposit( + genesis_validator_deposits.append(spec.Deposit( proof=list(get_merkle_proof(tree, item_index=i)), index=i, data=deposit_data_list[i] @@ -113,10 +73,10 @@ def create_genesis_state(num_validators, deposit_data_leaves=None): num_validators, deposit_data_leaves, ) - return get_genesis_beacon_state( + return spec.get_genesis_beacon_state( initial_deposits, genesis_time=0, - genesis_eth1_data=Eth1Data( + genesis_eth1_data=spec.Eth1Data( deposit_root=deposit_root, deposit_count=len(initial_deposits), block_hash=spec.ZERO_HASH, @@ -125,7 +85,7 @@ def create_genesis_state(num_validators, deposit_data_leaves=None): def build_empty_block_for_next_slot(state): - empty_block = BeaconBlock() + empty_block = spec.BeaconBlock() empty_block.slot = state.slot + 1 empty_block.body.eth1_data.deposit_count = state.deposit_index previous_block_header = deepcopy(state.latest_block_header) @@ -136,16 +96,16 @@ def build_empty_block_for_next_slot(state): def build_deposit_data(state, pubkey, privkey, amount): - deposit_data = DepositData( + deposit_data = spec.DepositData( pubkey=pubkey, # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + hash(pubkey)[1:], + withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], amount=amount, ) signature = bls.sign( message_hash=signing_root(deposit_data), privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state, spec.DOMAIN_DEPOSIT, ) @@ -160,15 +120,15 @@ def build_attestation_data(state, slot, shard): if slot == state.slot: block_root = build_empty_block_for_next_slot(state).parent_root else: - block_root = get_block_root_at_slot(state, slot) + block_root = spec.get_block_root_at_slot(state, slot) - current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state)) + current_epoch_start_slot = spec.get_epoch_start_slot(spec.get_current_epoch(state)) if slot < current_epoch_start_slot: - epoch_boundary_root = get_block_root(state, get_previous_epoch(state)) + epoch_boundary_root = spec.get_block_root(state, spec.get_previous_epoch(state)) elif slot == current_epoch_start_slot: epoch_boundary_root = block_root else: - epoch_boundary_root = get_block_root(state, get_current_epoch(state)) + epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state)) if slot < current_epoch_start_slot: justified_epoch = state.previous_justified_epoch @@ -177,31 +137,31 @@ def build_attestation_data(state, slot, shard): justified_epoch = state.current_justified_epoch justified_block_root = state.current_justified_root - crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks - return AttestationData( + crosslinks = state.current_crosslinks if spec.slot_to_epoch(slot) == spec.get_current_epoch(state) else state.previous_crosslinks + return spec.AttestationData( beacon_block_root=block_root, source_epoch=justified_epoch, source_root=justified_block_root, - target_epoch=slot_to_epoch(slot), + target_epoch=spec.slot_to_epoch(slot), target_root=epoch_boundary_root, - crosslink=Crosslink( + crosslink=spec.Crosslink( shard=shard, - epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK), + epoch=min(spec.slot_to_epoch(slot), crosslinks[shard].epoch + spec.MAX_EPOCHS_PER_CROSSLINK), data_root=spec.ZERO_HASH, - parent_root=hash_tree_root(crosslinks[shard]), + parent_root=spec.hash_tree_root(crosslinks[shard]), ), ) def build_voluntary_exit(state, epoch, validator_index, privkey): - voluntary_exit = VoluntaryExit( + voluntary_exit = spec.VoluntaryExit( epoch=epoch, validator_index=validator_index, ) voluntary_exit.signature = bls.sign( message_hash=signing_root(voluntary_exit), privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_VOLUNTARY_EXIT, message_epoch=epoch, @@ -224,9 +184,9 @@ def build_deposit(state, tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) root = get_merkle_root((tuple(deposit_data_leaves))) proof = list(get_merkle_proof(tree, item_index=index)) - assert verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) + assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) - deposit = Deposit( + deposit = spec.Deposit( proof=list(proof), index=index, data=deposit_data, @@ -236,22 +196,22 @@ def build_deposit(state, def get_valid_proposer_slashing(state): - current_epoch = get_current_epoch(state) - validator_index = get_active_validator_indices(state, current_epoch)[-1] + current_epoch = spec.get_current_epoch(state) + validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] slot = state.slot - header_1 = BeaconBlockHeader( + header_1 = spec.BeaconBlockHeader( slot=slot, - parent_root=ZERO_HASH, - state_root=ZERO_HASH, - body_root=ZERO_HASH, + parent_root=spec.ZERO_HASH, + state_root=spec.ZERO_HASH, + body_root=spec.ZERO_HASH, ) header_2 = deepcopy(header_1) header_2.parent_root = b'\x02' * 32 header_2.slot = slot + 1 - domain = get_domain( + domain = spec.get_domain( state=state, domain_type=spec.DOMAIN_BEACON_PROPOSER, ) @@ -266,7 +226,7 @@ def get_valid_proposer_slashing(state): domain=domain, ) - return ProposerSlashing( + return spec.ProposerSlashing( proposer_index=validator_index, header_1=header_1, header_2=header_2, @@ -278,9 +238,9 @@ def get_valid_attester_slashing(state): attestation_2 = deepcopy(attestation_1) attestation_2.data.target_root = b'\x01' * 32 - return AttesterSlashing( - attestation_1=convert_to_indexed(state, attestation_1), - attestation_2=convert_to_indexed(state, attestation_2), + return spec.AttesterSlashing( + attestation_1=spec.convert_to_indexed(state, attestation_1), + attestation_2=spec.convert_to_indexed(state, attestation_2), ) @@ -288,26 +248,26 @@ def get_valid_attestation(state, slot=None): if slot is None: slot = state.slot - if slot_to_epoch(slot) == get_current_epoch(state): + if spec.slot_to_epoch(slot) == spec.get_current_epoch(state): shard = (state.latest_start_shard + slot) % spec.SLOTS_PER_EPOCH else: - previous_shard_delta = get_shard_delta(state, get_previous_epoch(state)) + previous_shard_delta = spec.get_shard_delta(state, spec.get_previous_epoch(state)) shard = (state.latest_start_shard - previous_shard_delta + slot) % spec.SHARD_COUNT attestation_data = build_attestation_data(state, slot, shard) - crosslink_committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) committee_size = len(crosslink_committee) bitfield_length = (committee_size + 7) // 8 aggregation_bitfield = b'\xC0' + b'\x00' * (bitfield_length - 1) custody_bitfield = b'\x00' * bitfield_length - attestation = Attestation( + attestation = spec.Attestation( aggregation_bitfield=aggregation_bitfield, data=attestation_data, custody_bitfield=custody_bitfield, ) - participants = get_attesting_indices( + participants = spec.get_attesting_indices( state, attestation.data, attestation.aggregation_bitfield, @@ -332,10 +292,10 @@ def get_valid_attestation(state, slot=None): def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=None): if slot is None: slot = state.slot - current_epoch = get_current_epoch(state) + current_epoch = spec.get_current_epoch(state) if sender_index is None: - sender_index = get_active_validator_indices(state, current_epoch)[-1] - recipient_index = get_active_validator_indices(state, current_epoch)[0] + sender_index = spec.get_active_validator_indices(state, current_epoch)[-1] + recipient_index = spec.get_active_validator_indices(state, current_epoch)[0] transfer_pubkey = pubkeys[-1] transfer_privkey = privkeys[-1] @@ -344,22 +304,22 @@ def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=Non if amount is None: amount = get_balance(state, sender_index) - fee - transfer = Transfer( + transfer = spec.Transfer( sender=sender_index, recipient=recipient_index, amount=amount, fee=fee, slot=slot, pubkey=transfer_pubkey, - signature=ZERO_HASH, + signature=spec.ZERO_HASH, ) transfer.signature = bls.sign( message_hash=signing_root(transfer), privkey=transfer_privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_TRANSFER, - message_epoch=get_current_epoch(state), + message_epoch=spec.get_current_epoch(state), ) ) @@ -372,7 +332,7 @@ def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=Non def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0): - message_hash = AttestationDataAndCustodyBit( + message_hash = spec.AttestationDataAndCustodyBit( data=attestation_data, custody_bit=custody_bit, ).hash_tree_root() @@ -380,7 +340,7 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) return bls.sign( message_hash=message_hash, privkey=privkey, - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_ATTESTATION, message_epoch=attestation_data.target_epoch, @@ -389,7 +349,7 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) def fill_aggregate_attestation(state, attestation): - crosslink_committee = get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) for i in range(len(crosslink_committee)): attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) @@ -398,7 +358,7 @@ def add_attestation_to_state(state, attestation, slot): block = build_empty_block_for_next_slot(state) block.slot = slot block.body.attestations.append(attestation) - state_transition(state, block) + spec.state_transition(state, block) def next_slot(state): @@ -407,7 +367,7 @@ def next_slot(state): Return the empty block that triggered the transition. """ block = build_empty_block_for_next_slot(state) - state_transition(state, block) + spec.state_transition(state, block) return block @@ -418,7 +378,7 @@ def next_epoch(state): """ block = build_empty_block_for_next_slot(state) block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - state_transition(state, block) + spec.state_transition(state, block) return block diff --git a/test_libs/pyspec/tests/phase0/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py index be8ecaa1d..9e2fc361b 100644 --- a/test_libs/pyspec/tests/phase0/test_finality.py +++ b/test_libs/pyspec/tests/phase0/test_finality.py @@ -42,7 +42,7 @@ def next_epoch_with_attestations(state, block = helpers.build_empty_block_for_next_slot(post_state) if fill_cur_epoch: slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 - if slot_to_attest >= helpers.get_epoch_start_slot(helpers.get_current_epoch(post_state)): + if slot_to_attest >= spec.get_epoch_start_slot(spec.get_current_epoch(post_state)): cur_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) helpers.fill_aggregate_attestation(post_state, cur_attestation) block.body.attestations.append(cur_attestation) diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 62dd2be38..53976aeeb 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -3,27 +3,35 @@ import pytest from eth2spec.phase1 import spec from preset_loader import loader +from tests.phase0 import helpers as phase1_helpers from tests.phase1 import helpers as helpers from tests.phase0.conftest import ( - pytest_addoption, deposit_data_leaves, ) -# This is redfined so that the constants are re-applied +def pytest_addoption(parser): + parser.addoption( + "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" + ) + + @pytest.fixture(autouse=True) def config(request): - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers config_name = request.config.getoption("--config") presets = loader.load_presets('../../configs/', config_name) spec.apply_constants_preset(presets) + helpers.spec = spec + phase1_helpers.spec = spec + request.function.__globals__['spec'] = spec + request.function.__globals__['helpers'] = helpers + @pytest.fixture def num_validators(config): return spec.SLOTS_PER_EPOCH * 8 -#This is redefined so that the BeaconState is the new SSZ Object + @pytest.fixture def state(num_validators, deposit_data_leaves): return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index b56266617..5962e45d1 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -1,48 +1,35 @@ from py_ecc import bls -import eth2spec.phase1.spec as spec -from eth2spec.phase1.spec import ( - # constants - CUSTODY_PERIOD_TO_RANDAO_PADDING, - # SSZ - EarlyDerivedSecretReveal, - # functions - get_active_validator_indices, - get_current_epoch, - get_domain, - hash_tree_root, -) - from tests.phase0.helpers import * def get_valid_early_derived_secret_reveal(state, epoch=None): - current_epoch = get_current_epoch(state) - revealed_index = get_active_validator_indices(state, current_epoch)[-1] - masker_index = get_active_validator_indices(state, current_epoch)[0] + current_epoch = spec.get_current_epoch(state) + revealed_index = spec.get_active_validator_indices(state, current_epoch)[-1] + masker_index = spec.get_active_validator_indices(state, current_epoch)[0] if epoch is None: - epoch = current_epoch + CUSTODY_PERIOD_TO_RANDAO_PADDING + epoch = current_epoch + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING reveal = bls.sign( - message_hash=hash_tree_root(epoch), + message_hash=spec.hash_tree_root(epoch), privkey=privkeys[revealed_index], - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, message_epoch=epoch, ), ) mask = bls.sign( - message_hash=hash_tree_root(epoch), + message_hash=spec.hash_tree_root(epoch), privkey=privkeys[masker_index], - domain=get_domain( + domain=spec.get_domain( state=state, domain_type=spec.DOMAIN_RANDAO, message_epoch=epoch, ), ) - return EarlyDerivedSecretReveal( + return spec.EarlyDerivedSecretReveal( revealed_index=revealed_index, epoch=epoch, reveal=reveal, From 24c4d21d5ef00060cb57cc5cc1b532adae34625d Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Tue, 21 May 2019 12:41:24 +0200 Subject: [PATCH 27/55] Minor edits + PEP8 --- Makefile | 4 +- scripts/build_spec.py | 1 - specs/core/0_beacon-chain.md | 6 +- specs/core/1_custody-game.md | 25 +++++--- specs/core/1_shard-data-chains.md | 2 +- .../eth2spec/phase1/state_transition.py | 4 +- .../pyspec/eth2spec/utils/minimal_ssz.py | 2 - .../block_processing/test_process_transfer.py | 8 ++- test_libs/pyspec/tests/phase0/conftest.py | 6 +- .../test_process_crosslinks.py | 5 +- test_libs/pyspec/tests/phase0/helpers.py | 21 +++++-- test_libs/pyspec/tests/phase0/test_sanity.py | 1 - ...est_process_early_derived_secret_reveal.py | 60 ++++++++++++------- test_libs/pyspec/tests/phase1/conftest.py | 3 +- test_libs/pyspec/tests/phase1/helpers.py | 1 + 15 files changed, 97 insertions(+), 52 deletions(-) diff --git a/Makefile b/Makefile index 041916fab..443266bb4 100644 --- a/Makefile +++ b/Makefile @@ -52,11 +52,11 @@ citest: $(PY_SPEC_ALL_TARGETS) python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase1 install_lint: - cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.5.0 + cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.7.0 lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ - flake8 --max-line-length=120 ./eth2spec; + flake8 --max-line-length=120 --per-file-ignores='./tests/*:F821,F403,F401,F405' ./eth2spec ./tests; # "make pyspec" to create the pyspec for all phases. pyspec: $(PY_SPEC_ALL_TARGETS) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 9e1d0436a..a1f3794da 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -50,7 +50,6 @@ from eth2spec.utils.bls_stub import ( ) from eth2spec.utils.hash_function import hash -import math ''' NEW_TYPES = { 'Slot': 'int', diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index f69795926..281c3d9ee 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -962,7 +962,7 @@ def get_total_balance(state: BeaconState, indices: List[ValidatorIndex]) -> Gwei ```python def get_domain(state: BeaconState, domain_type: int, - message_epoch: int=None) -> int: + message_epoch: int = None) -> int: """ Return the signature domain (fork version concatenated with domain type) of a message. """ @@ -1150,7 +1150,7 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: ```python def slash_validator(state: BeaconState, slashed_index: ValidatorIndex, - whistleblower_index: ValidatorIndex=None) -> None: + whistleblower_index: ValidatorIndex = None) -> None: """ Slash the validator with index ``slashed_index``. """ @@ -1223,7 +1223,7 @@ Let `genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state))`. The post-state corresponding to a pre-state `state` and a block `block` is defined as `state_transition(state, block)`. State transitions that trigger an unhandled excpetion (e.g. a failed `assert` or an out-of-range list access) are considered invalid. ```python -def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool=False) -> BeaconState: +def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool = False) -> BeaconState: # Process slots (including those with no blocks) since block process_slots(state, block.slot) # Process block diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 9831c52ec..ee9867007 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -33,6 +33,7 @@ - [Helpers](#helpers) - [`type_of`](#type_of) - [`empty`](#empty) + - [`ceillog2`](#ceillog2) - [`get_crosslink_chunk_count`](#get_crosslink_chunk_count) - [`get_custody_chunk_bit`](#get_custody_chunk_bit) - [`get_chunk_bits_root`](#get_chunk_bits_root) @@ -126,7 +127,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'attestation': Attestation, 'challenger_index': ValidatorIndex, 'responder_key': BLSSignature, - 'chunk_bits': "bytes", + 'chunk_bits': 'bytes', 'signature': BLSSignature, } ``` @@ -257,6 +258,13 @@ The `type_of` function accepts an SSZ object as a single input and returns the c The `empty` function accepts an SSZ type as input and returns an object of that type with all fields initialized to default values. +### `ceillog2` + +```python +def ceillog2(x): + return x.bit_length() +``` + ### `get_crosslink_chunk_count` ```python @@ -298,7 +306,7 @@ def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorI ```python def get_validators_custody_reveal_period(state: BeaconState, validator_index: ValidatorIndex, - epoch: Epoch=None) -> int: + epoch: Epoch = None) -> int: ''' This function returns the reveal period for a given validator. If no epoch is supplied, the current epoch is assumed. @@ -479,7 +487,7 @@ def process_chunk_challenge(state: BeaconState, record.chunk_index != challenge.chunk_index ) # Verify depth - depth = math.ceil(math.log2(get_custody_chunk_count(challenge.attestation.data.crosslink))) + depth = ceillog2(get_custody_chunk_count(challenge.attestation.data.crosslink)) assert challenge.chunk_index < 2**depth # Add new chunk challenge record new_record = CustodyChunkChallengeRecord( @@ -637,7 +645,7 @@ def process_bit_challenge_response(state: BeaconState, assert verify_merkle_branch( leaf=hash_tree_root(response.chunk), branch=response.data_branch, - depth=math.ceil(math.log2(challenge.chunk_count)), + depth=ceillog2(challenge.chunk_count), index=response.chunk_index, root=challenge.data_root, ) @@ -645,7 +653,7 @@ def process_bit_challenge_response(state: BeaconState, assert verify_merkle_branch( leaf=response.chunk_bits_leaf, branch=response.chunk_bits_branch, - depth=math.ceil(math.log2(challenge.chunk_count)) >> 8, + depth=ceillog2(challenge.chunk_count) >> 8, index=response.chunk_index // 256, root=challenge.chunk_bits_merkle_root ) @@ -668,10 +676,9 @@ Run `process_reveal_deadlines(state)` immediately after `process_registry_update ```python def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): - if (validator.next_custody_reveal_period + - (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) < - get_validators_custody_reveal_period(state, index)): - slash_validator(state, index) + if (validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) + < get_validators_custody_reveal_period(state, index)): + slash_validator(state, index) ``` Run `process_challenge_deadlines(state)` immediately after `process_reveal_deadlines(state)`: diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 8619354e4..7cb4bd78b 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -236,7 +236,7 @@ def verify_shard_attestation_signature(state: BeaconState, ### `compute_crosslink_data_root` ```python -def compute_crosslink_data_root(blocks: List[ShardBlock]) -> 'bytes32': +def compute_crosslink_data_root(blocks: List[ShardBlock]) -> Bytes32: def is_power_of_two(value: int) -> bool: return (value > 0) and (value & (value - 1) == 0) diff --git a/test_libs/pyspec/eth2spec/phase1/state_transition.py b/test_libs/pyspec/eth2spec/phase1/state_transition.py index 87b2e1c12..a2a78d273 100644 --- a/test_libs/pyspec/eth2spec/phase1/state_transition.py +++ b/test_libs/pyspec/eth2spec/phase1/state_transition.py @@ -32,7 +32,7 @@ def process_operations(state: BeaconState, block: BeaconBlock) -> None: def process_block(state: BeaconState, block: BeaconBlock, - verify_state_root: bool=False) -> None: + verify_state_root: bool = False) -> None: spec.process_block_header(state, block) spec.process_randao(state, block) spec.process_eth1_data(state, block) @@ -65,6 +65,6 @@ def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState: def state_transition(state: BeaconState, block: BeaconBlock, - verify_state_root: bool=False) -> BeaconState: + verify_state_root: bool = False) -> BeaconState: state_transition_to(state, block.slot) process_block(state, block, verify_state_root) diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index 63516780e..f46c0acef 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -6,8 +6,6 @@ BYTES_PER_CHUNK = 32 BYTES_PER_LENGTH_OFFSET = 4 ZERO_CHUNK = b'\x00' * BYTES_PER_CHUNK -cached_typedefs = {} - def SSZType(fields): class SSZObject(): diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py index 724c69647..2d37798e7 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py @@ -18,7 +18,6 @@ def run_transfer_processing(state, transfer, valid=True): spec.process_transfer(post_state, transfer) return state, None - spec.process_transfer(post_state, transfer) proposer_index = spec.get_beacon_proposer_index(state) @@ -106,7 +105,12 @@ def test_insufficient_balance(state): def test_no_dust(state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] balance = state.balances[sender_index] - transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, fee=0) + transfer = helpers.get_valid_transfer( + state, + sender_index=sender_index, + amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, + fee=0 + ) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py index 0549a1422..67dc34fa4 100644 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ b/test_libs/pyspec/tests/phase0/conftest.py @@ -4,13 +4,14 @@ from eth2spec.phase0 import spec from preset_loader import loader from tests.phase0 import helpers -from tests.phase0 import test_finality + def pytest_addoption(parser): parser.addoption( "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" ) + @pytest.fixture(autouse=True) def config(request): config_name = request.config.getoption("--config") @@ -20,14 +21,17 @@ def config(request): request.function.__globals__['spec'] = spec request.function.__globals__['helpers'] = helpers + @pytest.fixture def num_validators(config): return spec.SLOTS_PER_EPOCH * 8 + @pytest.fixture def deposit_data_leaves(): return list() + @pytest.fixture def state(num_validators, deposit_data_leaves): return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py index 19c668e74..e4913734c 100644 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py @@ -108,7 +108,10 @@ def test_double_late_crosslink(state): # ensure that the current crosslinks were not updated by the second attestation assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink - for index in spec.get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): + for index in spec.get_crosslink_committee( + state, + attestation_2.data.target_epoch, + attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/phase0/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py index c73277f96..d41ddd59d 100644 --- a/test_libs/pyspec/tests/phase0/helpers.py +++ b/test_libs/pyspec/tests/phase0/helpers.py @@ -14,6 +14,7 @@ privkeys = [i + 1 for i in range(1024)] pubkeys = [bls.privtopub(privkey) for privkey in privkeys] pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} + def advance_slot(state) -> None: state.slot += 1 @@ -137,7 +138,10 @@ def build_attestation_data(state, slot, shard): justified_epoch = state.current_justified_epoch justified_block_root = state.current_justified_root - crosslinks = state.current_crosslinks if spec.slot_to_epoch(slot) == spec.get_current_epoch(state) else state.previous_crosslinks + crosslinks = ( + state.current_crosslinks if spec.slot_to_epoch(slot) == spec.get_current_epoch(state) + else state.previous_crosslinks + ) parent_crosslink = crosslinks[shard] return spec.AttestationData( beacon_block_root=block_root, @@ -258,7 +262,11 @@ def get_valid_attestation(state, slot=None): attestation_data = build_attestation_data(state, slot, shard) - crosslink_committee = spec.get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee( + state, + attestation_data.target_epoch, + attestation_data.crosslink.shard + ) committee_size = len(crosslink_committee) bitfield_length = (committee_size + 7) // 8 @@ -351,7 +359,11 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) def fill_aggregate_attestation(state, attestation): - crosslink_committee = spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) + crosslink_committee = spec.get_crosslink_committee( + state, + attestation.data.target_epoch, + attestation.data.crosslink.shard + ) for i in range(len(crosslink_committee)): attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) @@ -390,6 +402,3 @@ def get_state_root(state, slot) -> bytes: """ assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT return state.latest_state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT] - -# Stub to be overwritten by config -import_spec = None \ No newline at end of file diff --git a/test_libs/pyspec/tests/phase0/test_sanity.py b/test_libs/pyspec/tests/phase0/test_sanity.py index 821d97386..47e4917ab 100644 --- a/test_libs/pyspec/tests/phase0/test_sanity.py +++ b/test_libs/pyspec/tests/phase0/test_sanity.py @@ -227,7 +227,6 @@ def test_attestation(state): assert len(test_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1 - # # Epoch transition should move to previous_epoch_attestations # diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index 08f7cf9ac..75c44697c 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -1,10 +1,11 @@ from copy import deepcopy import pytest -#mark entire file as 'randao_key_reveals' +# mark entire file as 'randao_key_reveals' pytestmark = pytest.mark.randao_key_reveals -def terun_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): + +def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): """ Run ``process_randao_key_reveal`` returning the pre and post state. If ``valid == False``, run expecting ``AssertionError`` @@ -37,7 +38,7 @@ def terun_early_derived_secret_reveal_processing(state, randao_key_reveal, valid def test_success(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) return pre_state, randao_key_reveal, post_state @@ -45,52 +46,71 @@ def test_success(state): def test_reveal_from_current_epoch(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state @pytest.mark.skip(reason="Not currently possible as we are testing at epoch 0") def test_reveal_from_past_epoch(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) - 1) + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) - 1) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + + return pre_state, randao_key_reveal, post_state - return pre_state, randao_key_reveal, post_state def test_reveal_with_custody_padding(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( + state, + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING + ) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state + def test_reveal_with_custody_padding_minus_one(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, True) + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( + state, + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1 + ) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) return pre_state, randao_key_reveal, post_state + def test_double_reveal(state): - - randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1) - pre_state, intermediate_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal1) - - randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal(intermediate_state, spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1) - _, post_state = terun_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) + randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal( + state, + spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1 + ) + pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) + + randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal( + intermediate_state, + spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1 + ) + _, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + def test_revealer_is_slashed(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) state.validator_registry[randao_key_reveal.revealed_index].slashed = True - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state + def test_far_future_epoch(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS) + randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( + state, + spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS + ) - pre_state, post_state = terun_early_derived_secret_reveal_processing(state, randao_key_reveal, False) + pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) return pre_state, randao_key_reveal, post_state diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 53976aeeb..0e634cbf4 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -10,6 +10,7 @@ from tests.phase0.conftest import ( deposit_data_leaves, ) + def pytest_addoption(parser): parser.addoption( "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" @@ -33,5 +34,5 @@ def num_validators(config): @pytest.fixture -def state(num_validators, deposit_data_leaves): +def state(num_validators, deposit_data_leaves): # noqa: F811 return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py index 5962e45d1..d7adbd802 100644 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ b/test_libs/pyspec/tests/phase1/helpers.py @@ -2,6 +2,7 @@ from py_ecc import bls from tests.phase0.helpers import * + def get_valid_early_derived_secret_reveal(state, epoch=None): current_epoch = spec.get_current_epoch(state) revealed_index = spec.get_active_validator_indices(state, current_epoch)[-1] From 9058647b67dbce3631d13a61c93fc5fc01e8e9aa Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 22 May 2019 10:28:03 +0200 Subject: [PATCH 28/55] flake8v3.7->flake8v3.5 --- Makefile | 5 +++-- specs/core/0_beacon-chain.md | 6 +++--- specs/core/1_custody-game.md | 2 +- test_libs/pyspec/eth2spec/phase1/state_transition.py | 4 ++-- .../phase0/block_processing/test_process_transfer.py | 4 ++-- test_libs/pyspec/tests/phase0/helpers.py | 6 +++--- .../test_process_early_derived_secret_reveal.py | 10 +++++----- test_libs/pyspec/tests/phase1/conftest.py | 11 ++++++----- 8 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 443266bb4..d700d1900 100644 --- a/Makefile +++ b/Makefile @@ -52,11 +52,12 @@ citest: $(PY_SPEC_ALL_TARGETS) python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase1 install_lint: - cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.7.0 + cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.5.0 lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ - flake8 --max-line-length=120 --per-file-ignores='./tests/*:F821,F403,F401,F405' ./eth2spec ./tests; + flake8 --max-line-length=120 ./eth2spec; \ + flake8 --max-line-length=120 --ignore=F401,F403,F405,F821 ./tests; # "make pyspec" to create the pyspec for all phases. pyspec: $(PY_SPEC_ALL_TARGETS) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 281c3d9ee..f69795926 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -962,7 +962,7 @@ def get_total_balance(state: BeaconState, indices: List[ValidatorIndex]) -> Gwei ```python def get_domain(state: BeaconState, domain_type: int, - message_epoch: int = None) -> int: + message_epoch: int=None) -> int: """ Return the signature domain (fork version concatenated with domain type) of a message. """ @@ -1150,7 +1150,7 @@ def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None: ```python def slash_validator(state: BeaconState, slashed_index: ValidatorIndex, - whistleblower_index: ValidatorIndex = None) -> None: + whistleblower_index: ValidatorIndex=None) -> None: """ Slash the validator with index ``slashed_index``. """ @@ -1223,7 +1223,7 @@ Let `genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state))`. The post-state corresponding to a pre-state `state` and a block `block` is defined as `state_transition(state, block)`. State transitions that trigger an unhandled excpetion (e.g. a failed `assert` or an out-of-range list access) are considered invalid. ```python -def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool = False) -> BeaconState: +def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool=False) -> BeaconState: # Process slots (including those with no blocks) since block process_slots(state, block.slot) # Process block diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index ee9867007..b96ea613a 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -306,7 +306,7 @@ def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorI ```python def get_validators_custody_reveal_period(state: BeaconState, validator_index: ValidatorIndex, - epoch: Epoch = None) -> int: + epoch: Epoch=None) -> int: ''' This function returns the reveal period for a given validator. If no epoch is supplied, the current epoch is assumed. diff --git a/test_libs/pyspec/eth2spec/phase1/state_transition.py b/test_libs/pyspec/eth2spec/phase1/state_transition.py index a2a78d273..87b2e1c12 100644 --- a/test_libs/pyspec/eth2spec/phase1/state_transition.py +++ b/test_libs/pyspec/eth2spec/phase1/state_transition.py @@ -32,7 +32,7 @@ def process_operations(state: BeaconState, block: BeaconBlock) -> None: def process_block(state: BeaconState, block: BeaconBlock, - verify_state_root: bool = False) -> None: + verify_state_root: bool=False) -> None: spec.process_block_header(state, block) spec.process_randao(state, block) spec.process_eth1_data(state, block) @@ -65,6 +65,6 @@ def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState: def state_transition(state: BeaconState, block: BeaconBlock, - verify_state_root: bool = False) -> BeaconState: + verify_state_root: bool=False) -> BeaconState: state_transition_to(state, block.slot) process_block(state, block, verify_state_root) diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py index 2d37798e7..6c57c54f0 100644 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py @@ -79,7 +79,7 @@ def test_active_but_transfer_past_effective_balance(state): def test_incorrect_slot(state): - transfer = helpers.get_valid_transfer(state, slot=state.slot+1) + transfer = helpers.get_valid_transfer(state, slot=state.slot + 1) # un-activate so validator can transfer state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH @@ -109,7 +109,7 @@ def test_no_dust(state): state, sender_index=sender_index, amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, - fee=0 + fee=0, ) # un-activate so validator can transfer diff --git a/test_libs/pyspec/tests/phase0/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py index d41ddd59d..4d1973921 100644 --- a/test_libs/pyspec/tests/phase0/helpers.py +++ b/test_libs/pyspec/tests/phase0/helpers.py @@ -32,7 +32,7 @@ def set_bitfield_bit(bitfield, i): return ( bitfield[:byte_index] + bytes([bitfield[byte_index] | (1 << bit_index)]) + - bitfield[byte_index+1:] + bitfield[byte_index + 1:] ) @@ -265,7 +265,7 @@ def get_valid_attestation(state, slot=None): crosslink_committee = spec.get_crosslink_committee( state, attestation_data.target_epoch, - attestation_data.crosslink.shard + attestation_data.crosslink.shard, ) committee_size = len(crosslink_committee) @@ -362,7 +362,7 @@ def fill_aggregate_attestation(state, attestation): crosslink_committee = spec.get_crosslink_committee( state, attestation.data.target_epoch, - attestation.data.crosslink.shard + attestation.data.crosslink.shard, ) for i in range(len(crosslink_committee)): attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py index 75c44697c..ad436ff29 100644 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py @@ -63,7 +63,7 @@ def test_reveal_from_past_epoch(state): def test_reveal_with_custody_padding(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( state, - spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING, ) pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) @@ -73,7 +73,7 @@ def test_reveal_with_custody_padding(state): def test_reveal_with_custody_padding_minus_one(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( state, - spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1 + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1, ) pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) @@ -83,13 +83,13 @@ def test_reveal_with_custody_padding_minus_one(state): def test_double_reveal(state): randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal( state, - spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1 + spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1, ) pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal( intermediate_state, - spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1 + spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, ) _, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) @@ -108,7 +108,7 @@ def test_revealer_is_slashed(state): def test_far_future_epoch(state): randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( state, - spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS + spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, ) pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py index 0e634cbf4..4226241d7 100644 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ b/test_libs/pyspec/tests/phase1/conftest.py @@ -6,10 +6,6 @@ from preset_loader import loader from tests.phase0 import helpers as phase1_helpers from tests.phase1 import helpers as helpers -from tests.phase0.conftest import ( - deposit_data_leaves, -) - def pytest_addoption(parser): parser.addoption( @@ -34,5 +30,10 @@ def num_validators(config): @pytest.fixture -def state(num_validators, deposit_data_leaves): # noqa: F811 +def deposit_data_leaves(): + return list() + + +@pytest.fixture +def state(num_validators, deposit_data_leaves): return helpers.create_genesis_state(num_validators, deposit_data_leaves) From 271f615873e3165e0ea345125b10ff56cf07f53e Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 22 May 2019 12:40:57 +0200 Subject: [PATCH 29/55] Dramatically speed up tests --- configs/constant_presets/minimal.yaml | 2 ++ scripts/build_spec.py | 2 +- .../{test_phase0.py => test_phase0_epoch_processing.py} | 0 3 files changed, 3 insertions(+), 1 deletion(-) rename test_libs/pyspec/tests/phase1/epoch_processing/{test_phase0.py => test_phase0_epoch_processing.py} (100%) diff --git a/configs/constant_presets/minimal.yaml b/configs/constant_presets/minimal.yaml index caae4623b..73448c3c6 100644 --- a/configs/constant_presets/minimal.yaml +++ b/configs/constant_presets/minimal.yaml @@ -74,6 +74,8 @@ PERSISTENT_COMMITTEE_PERIOD: 2048 MAX_EPOCHS_PER_CROSSLINK: 64 # 2**2 (= 4) epochs 25.6 minutes MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 +# [customized] 2**12 (= 4,096) epochs 18 days +EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS: 4096 # State list lengths diff --git a/scripts/build_spec.py b/scripts/build_spec.py index a1f3794da..7619efbe7 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -114,7 +114,7 @@ def objects_to_spec(functions, constants, ssz_objects, imports): constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) ssz_objects_instantiation_spec = '\n'.join(map(lambda x: '%s = SSZType(%s)' % (x, ssz_objects[x][:-1]), ssz_objects)) ssz_objects_reinitialization_spec = '\n'.join( - map(lambda x: ' global_vars[%s] = SSZType(%s })' % (x, re.sub('( ){4}', ' '*8, ssz_objects[x][:-2])), ssz_objects)) + map(lambda x: ' global_vars[\'%s\'] = SSZType(%s })' % (x, re.sub('( ){4}', ' '*8, ssz_objects[x][:-2])), ssz_objects)) ssz_objects_reinitialization_spec = ( 'def init_SSZ_types():\n global_vars = globals()\n' + ssz_objects_reinitialization_spec diff --git a/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py b/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py similarity index 100% rename from test_libs/pyspec/tests/phase1/epoch_processing/test_phase0.py rename to test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py From ac9564c2b73cf913387fdc604c87b242759aebce Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 24 May 2019 16:51:21 +0200 Subject: [PATCH 30/55] Adds Insert-into-label functionality --- scripts/build_spec.py | 24 ++++++++++++++++-------- scripts/function_puller.py | 30 ++++++++++++++++++++---------- specs/core/0_beacon-chain.md | 3 +++ specs/core/1_custody-game.md | 11 ++++++++++- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 7619efbe7..70051ef07 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -1,4 +1,3 @@ -import sys import re import function_puller from argparse import ArgumentParser @@ -108,7 +107,7 @@ def apply_constants_preset(preset: Dict[str, Any]): ''' -def objects_to_spec(functions, constants, ssz_objects, imports): +def objects_to_spec(functions, constants, ssz_objects, imports, inserts={}): new_type_definitions = '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) @@ -119,7 +118,7 @@ def objects_to_spec(functions, constants, ssz_objects, imports): 'def init_SSZ_types():\n global_vars = globals()\n' + ssz_objects_reinitialization_spec ) - return ( + spec = ( imports + '\n' + new_type_definitions + '\n\n' + constants_spec @@ -129,11 +128,15 @@ def objects_to_spec(functions, constants, ssz_objects, imports): + '\n\n' + ssz_objects_reinitialization_spec + '\n' ) + # Handle @inserts + for key, value in inserts.items(): + spec = re.sub('[ ]*# %s\\n' % key, value, spec) + return spec + def combine_functions(old_funcitons, new_functions): for key, value in new_functions.items(): old_funcitons[key] = value - # TODO: Add insert functionality return old_funcitons @@ -167,8 +170,12 @@ def combine_ssz_objects(old_objects, new_objects): return old_objects +# inserts are handeled the same way as functions +combine_inserts = combine_functions + + def build_phase0_spec(sourcefile, outfile=None): - functions, constants, ssz_objects = function_puller.get_spec(sourcefile) + functions, constants, ssz_objects, _ = function_puller.get_spec(sourcefile) spec = objects_to_spec(functions, constants, ssz_objects, PHASE0_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: @@ -178,12 +185,13 @@ def build_phase0_spec(sourcefile, outfile=None): def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): - phase0_functions, phase0_constants, phase0_ssz_objects = function_puller.get_spec(phase0_sourcefile) - phase1_functions, phase1_constants, phase1_ssz_objects = function_puller.get_spec(phase1_sourcefile) + phase0_functions, phase0_constants, phase0_ssz_objects, phase0_inserts = function_puller.get_spec(phase0_sourcefile) + phase1_functions, phase1_constants, phase1_ssz_objects, phase1_inserts = function_puller.get_spec(phase1_sourcefile) functions = combine_functions(phase0_functions, phase1_functions) constants = combine_constants(phase0_constants, phase1_constants) ssz_objects = combine_ssz_objects(phase0_ssz_objects, phase1_ssz_objects) - spec = objects_to_spec(functions, constants, ssz_objects, PHASE1_IMPORTS) + inserts = combine_inserts(phase0_inserts, phase1_inserts) + spec = objects_to_spec(functions, constants, ssz_objects, PHASE1_IMPORTS, inserts) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 29ecccfbf..72cb0365c 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -1,19 +1,22 @@ -import sys import re -from typing import List +from typing import Dict, Tuple FUNCTION_REGEX = r'^def [\w_]*' +BEGIN_INSERT_REGEX = r'# begin insert ' +END_INSERT_REGEX = r'# end insert' -def get_spec(file_name: str): - code_lines = [] - pulling_from = None # line number of start of latest object - current_name = None # most recent section title +def get_spec(file_name: str) -> Tuple[Dict[str, str], Dict[str, str], Dict[str, str], Dict[str, str]]: + pulling_from = None # line number of start of latest object + current_name = None # most recent section title + insert_name = None # stores the label of the current insert object functions = {} constants = {} ssz_objects = {} + inserts = {} function_matcher = re.compile(FUNCTION_REGEX) + inserts_matcher = re.compile(BEGIN_INSERT_REGEX) for linenum, line in enumerate(open(file_name).readlines()): line = line.rstrip() if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': @@ -23,12 +26,19 @@ def get_spec(file_name: str): pulling_from = linenum + 1 elif line[:3] == '```': pulling_from = None + elif inserts_matcher.match(line) is not None: + insert_name = re.search(r'@[\w]*', line).group(0) + elif insert_name is not None: + if re.match(END_INSERT_REGEX, line) is not None: + insert_name = None + else: + inserts[insert_name] = inserts.get(insert_name, '') + line + '\n' else: # Handle function definitions if pulling_from is not None: - match = function_matcher.match(line) - if match is not None: - current_name = match.group(0) + func_match = function_matcher.match(line) + if func_match is not None: + current_name = func_match.group(0) if function_matcher.match(current_name) is None: ssz_objects[current_name] = ssz_objects.get(current_name, '') + line + '\n' else: @@ -49,4 +59,4 @@ def get_spec(file_name: str): eligible = False if eligible: constants[row[0]] = row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890') - return functions, constants, ssz_objects + return functions, constants, ssz_objects, inserts diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 60f774e9a..be3e3d7d0 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1280,8 +1280,11 @@ def process_epoch(state: BeaconState) -> None: process_crosslinks(state) process_rewards_and_penalties(state) process_registry_updates(state) + # @process_reveal_deadlines + # @process_challenge_deadlines process_slashings(state) process_final_updates(state) + # @after_process_final_updates ``` #### Helper functions diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index b96ea613a..e71a92cd9 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -674,6 +674,9 @@ def process_bit_challenge_response(state: BeaconState, Run `process_reveal_deadlines(state)` immediately after `process_registry_updates(state)`: ```python +# begin insert @process_reveal_deadlines + process_reveal_deadlines(state) +# end insert @process_reveal_deadlines def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): if (validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) @@ -684,6 +687,9 @@ def process_reveal_deadlines(state: BeaconState) -> None: Run `process_challenge_deadlines(state)` immediately after `process_reveal_deadlines(state)`: ```python +# begin insert @process_challenge_deadlines + process_challenge_deadlines(state) +# end insert @process_challenge_deadlines def process_challenge_deadlines(state: BeaconState) -> None: for challenge in state.custody_chunk_challenge_records: if get_current_epoch(state) > challenge.inclusion_epoch + CUSTODY_RESPONSE_DEADLINE: @@ -701,12 +707,15 @@ def process_challenge_deadlines(state: BeaconState) -> None: Append this to `process_final_updates(state)`: ```python +# begin insert @after_process_final_updates + after_process_final_updates(state) +# end insert @after_process_final_updates def after_process_final_updates(state: BeaconState) -> None: current_epoch = get_current_epoch(state) # Clean up exposed RANDAO key reveals state.exposed_derived_secrets[current_epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS] = [] # Reset withdrawable epochs if challenge records are empty - records = state.custody_chunk_challenge_records + state.bit_challenge_records + records = state.custody_chunk_challenge_records + state.custody_bit_challenge_records validator_indices_in_records = set( [record.challenger_index for record in records] + [record.responder_index for record in records] ) From c4b9c6372c8b632fc931296d6e4b68c34e1dd2c5 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Sat, 25 May 2019 15:54:14 +0200 Subject: [PATCH 31/55] Merge in state_transition.py --- .../eth2spec/phase1/state_transition.py | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 test_libs/pyspec/eth2spec/phase1/state_transition.py diff --git a/test_libs/pyspec/eth2spec/phase1/state_transition.py b/test_libs/pyspec/eth2spec/phase1/state_transition.py deleted file mode 100644 index 87b2e1c12..000000000 --- a/test_libs/pyspec/eth2spec/phase1/state_transition.py +++ /dev/null @@ -1,70 +0,0 @@ -from . import spec - -from .spec import ( - BeaconState, - BeaconBlock, - Slot, -) - -from eth2spec.phase0.state_transition import ( - process_operation_type, - process_operations as process_operations_phase0, -) - - -def process_operations(state: BeaconState, block: BeaconBlock) -> None: - process_operations_phase0(state, block) - - process_operation_type( - state, - block.body.custody_key_reveals, - spec.MAX_CUSTODY_KEY_REVEALS, - spec.process_custody_key_reveal, - ) - - process_operation_type( - state, - block.body.early_derived_secret_reveals, - spec.MAX_EARLY_DERIVED_SECRET_REVEALS, - spec.process_early_derived_secret_reveal, - ) - - -def process_block(state: BeaconState, - block: BeaconBlock, - verify_state_root: bool=False) -> None: - spec.process_block_header(state, block) - spec.process_randao(state, block) - spec.process_eth1_data(state, block) - - process_operations(state, block) - if verify_state_root: - spec.verify_block_state_root(state, block) - - -def process_epoch_transition(state: BeaconState) -> None: - spec.process_justification_and_finalization(state) - spec.process_crosslinks(state) - # TODO: Eligible - spec.process_rewards_and_penalties(state) - spec.process_registry_updates(state) - spec.process_reveal_deadlines(state) - spec.process_challenge_deadlines(state) - spec.process_slashings(state) - spec.process_final_updates(state) - spec.after_process_final_updates(state) - - -def state_transition_to(state: BeaconState, up_to: Slot) -> BeaconState: - while state.slot < up_to: - spec.cache_state(state) - if (state.slot + 1) % spec.SLOTS_PER_EPOCH == 0: - process_epoch_transition(state) - spec.advance_slot(state) - - -def state_transition(state: BeaconState, - block: BeaconBlock, - verify_state_root: bool=False) -> BeaconState: - state_transition_to(state, block.slot) - process_block(state, block, verify_state_root) From a7dbbafc92e8b824e6f3f1b75c49e4c2aafb61ff Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Sun, 26 May 2019 14:14:48 +0200 Subject: [PATCH 32/55] Integrates shard-data-chains --- Makefile | 2 +- scripts/build_spec.py | 37 ++++++++++++++++++++----------- specs/core/1_shard-data-chains.md | 10 ++++----- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index d700d1900..0f74fc6d3 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ $(PY_SPEC_PHASE_0_TARGETS): $(PY_SPEC_PHASE_0_DEPS) python3 $(SCRIPT_DIR)/build_spec.py -p0 $(SPEC_DIR)/core/0_beacon-chain.md $@ $(PY_SPEC_DIR)/eth2spec/phase1/spec.py: $(PY_SPEC_PHASE_1_DEPS) - python3 $(SCRIPT_DIR)/build_spec.py -p1 $(SPEC_DIR)/core/0_beacon-chain.md $(SPEC_DIR)/core/1_custody-game.md $@ + python3 $(SCRIPT_DIR)/build_spec.py -p1 $(SPEC_DIR)/core/0_beacon-chain.md $(SPEC_DIR)/core/1_custody-game.md $(SPEC_DIR)/core/1_shard-data-chains.md $@ CURRENT_DIR = ${CURDIR} diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 70051ef07..a1d390a95 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -107,7 +107,7 @@ def apply_constants_preset(preset: Dict[str, Any]): ''' -def objects_to_spec(functions, constants, ssz_objects, imports, inserts={}): +def objects_to_spec(functions, constants, ssz_objects, inserts, imports): new_type_definitions = '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]),constants)) @@ -174,9 +174,19 @@ def combine_ssz_objects(old_objects, new_objects): combine_inserts = combine_functions +def combine_spec_objects(spec0, spec1): + functions0, constants0, ssz_objects0, inserts0 = spec0 + functions1, constants1, ssz_objects1, inserts1 = spec1 + functions = combine_functions(functions0, functions1) + constants = combine_constants(constants0, constants1) + ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1) + inserts = combine_inserts(inserts0, inserts1) + return functions, constants, ssz_objects, inserts + + def build_phase0_spec(sourcefile, outfile=None): - functions, constants, ssz_objects, _ = function_puller.get_spec(sourcefile) - spec = objects_to_spec(functions, constants, ssz_objects, PHASE0_IMPORTS) + functions, constants, ssz_objects, inserts = function_puller.get_spec(sourcefile) + spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) @@ -184,14 +194,14 @@ def build_phase0_spec(sourcefile, outfile=None): return spec -def build_phase1_spec(phase0_sourcefile, phase1_sourcefile, outfile=None): - phase0_functions, phase0_constants, phase0_ssz_objects, phase0_inserts = function_puller.get_spec(phase0_sourcefile) - phase1_functions, phase1_constants, phase1_ssz_objects, phase1_inserts = function_puller.get_spec(phase1_sourcefile) - functions = combine_functions(phase0_functions, phase1_functions) - constants = combine_constants(phase0_constants, phase1_constants) - ssz_objects = combine_ssz_objects(phase0_ssz_objects, phase1_ssz_objects) - inserts = combine_inserts(phase0_inserts, phase1_inserts) - spec = objects_to_spec(functions, constants, ssz_objects, PHASE1_IMPORTS, inserts) +def build_phase1_spec(phase0_sourcefile, phase1_custody_sourcefile, phase1_shard_sourcefile, outfile=None): + phase0_spec = function_puller.get_spec(phase0_sourcefile) + phase1_custody = function_puller.get_spec(phase1_custody_sourcefile) + phase1_shard_data = function_puller.get_spec(phase1_shard_sourcefile) + spec_objects = phase0_spec + for value in [phase1_custody, phase1_shard_data]: + spec_objects = combine_spec_objects(spec_objects, value) + spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) @@ -219,9 +229,10 @@ If building phase 1: if args.phase == 0: build_phase0_spec(*args.files) elif args.phase == 1: - if len(args.files) == 3: + print(args.files) + if len(args.files) == 4: build_phase1_spec(*args.files) else: - print(" Phase 1 requires an output as well as 2 input files (phase0.md and phase1.md)") + print(" Phase 1 requires an output as well as 3 input files (phase0.md and phase1.md, phase1.md)") else: print("Invalid phase: {0}".format(args.phase)) diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index aed570b80..746d5c733 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -47,7 +47,7 @@ This document describes the shard data layer and the shard fork choice rule in P | `BYTES_PER_SHARD_BLOCK_BODY` | `2**14` (= 16,384) | | `MAX_SHARD_ATTESTIONS` | `2**4` (= 16) | | `PHASE_1_GENESIS_EPOCH` | **TBD** | -| `PHASE_1_GENESIS_SLOT` | get_epoch_start_slot(PHASE_1_GENESIS_EPOCH) | +| `PHASE_1_GENESIS_SLOT` | **TBD** | ### Time parameters @@ -291,7 +291,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], # Check beacon block beacon_block = beacon_blocks[candidate.slot] assert candidate.beacon_block_root == signing_root(beacon_block) - assert beacon_block.slot <= candidate.slot: + assert beacon_block.slot <= candidate.slot # Check state root assert candidate.state_root == ZERO_HASH # [to be removed in phase 2] @@ -344,9 +344,9 @@ def is_valid_shard_attestation(valid_shard_blocks: List[ShardBlock], candidate: ShardAttestation) -> bool: # Check shard block shard_block = next( - block for block in valid_shard_blocks if - signing_root(block) == candidate.data.shard_block_root - , None) + (block for block in valid_shard_blocks if signing_root(block) == candidate.data.shard_block_root), + None, + ) assert shard_block != None assert shard_block.slot == candidate.data.slot assert shard_block.shard == candidate.data.shard From f7f069d6b5d3bac350d440c3137d7f7d031c9eb3 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Sun, 26 May 2019 19:41:36 +0200 Subject: [PATCH 33/55] Bug fixes and cleanup of 2_shard-data-chains --- specs/core/1_shard-data-chains.md | 46 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 746d5c733..f26b220d7 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -48,6 +48,7 @@ This document describes the shard data layer and the shard fork choice rule in P | `MAX_SHARD_ATTESTIONS` | `2**4` (= 16) | | `PHASE_1_GENESIS_EPOCH` | **TBD** | | `PHASE_1_GENESIS_SLOT` | **TBD** | +| `GENESIS_SHARD_SLOT` | 0 | ### Time parameters @@ -55,6 +56,7 @@ This document describes the shard data layer and the shard fork choice rule in P | - | - | :-: | :-: | | `CROSSLINK_LOOKBACK` | `2**0` (= 1) | epochs | 6.2 minutes | | `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days | +| `SECONDS_PER_SLOT` | `2**1 * 3**1` (= 6) | 6 seconds | ### Signature domains @@ -122,7 +124,11 @@ This document describes the shard data layer and the shard fork choice rule in P ### `get_period_committee` ```python -def get_period_committee(state: BeaconState, epoch: Epoch, shard: Shard, index: int, count: int) -> List[ValidatorIndex]: +def get_period_committee(state: BeaconState, + epoch: Epoch, + shard: Shard, + index: int, + count: int) -> List[ValidatorIndex]: """ Return committee for a period. Used to construct persistent committees. """ @@ -139,7 +145,8 @@ def get_period_committee(state: BeaconState, epoch: Epoch, shard: Shard, index: ```python def get_switchover_epoch(state: BeaconState, epoch: Epoch, index: ValidatorIndex): earlier_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2 - return bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + bytes3(index))[0:8]) % PERSISTENT_COMMITTEE_PERIOD + return (bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + bytes3(index))[0:8]) + % PERSISTENT_COMMITTEE_PERIOD) ``` ### `get_persistent_committee` @@ -245,15 +252,15 @@ def compute_crosslink_data_root(blocks: List[ShardBlock]) -> Bytes32: values += [b'\x00' * BYTES_PER_SHARD_BLOCK_BODY] return values - def merkle_root_of_bytes(data: bytes) -> bytes: - return merkle_root([data[i:i + 32] for i in range(0, len(data), 32)]) + def hash_tree_root_of_bytes(data: bytes) -> bytes: + return hash_tree_root([data[i:i + 32] for i in range(0, len(data), 32)]) return hash( - merkle_root(pad_to_power_of_2([ - merkle_root_of_bytes(zpad(serialize(get_shard_header(block)), BYTES_PER_SHARD_BLOCK_BODY)) for block in blocks + hash_tree_root(pad_to_power_of_2([ + hash_tree_root_of_bytes(zpad(serialize(get_shard_header(block)), BYTES_PER_SHARD_BLOCK_BODY)) for block in blocks ])) + - merkle_root(pad_to_power_of_2([ - merkle_root_of_bytes(block.body) for block in blocks + hash_tree_root(pad_to_power_of_2([ + hash_tree_root_of_bytes(block.body) for block in blocks ])) ) ``` @@ -301,10 +308,10 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], assert candidate.parent_root == ZERO_HASH else: parent_block = next( - (block for block in valid_shard_blocks if - signing_root(block) == candidate.parent_root) - , None) - assert parent_block != None + (block for block in valid_shard_blocks if signing_root(block) == candidate.parent_root), + None + ) + assert parent_block is not None assert parent_block.shard == candidate.shard assert parent_block.slot < candidate.slot assert signing_root(beacon_blocks[parent_block.slot]) == parent_block.beacon_chain_root @@ -321,10 +328,10 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], proposer_index = get_shard_proposer_index(beacon_state, candidate.shard, candidate.slot) assert proposer_index is not None assert bls_verify( - pubkey=validators[proposer_index].pubkey, + pubkey=beacon_state.validator_registry[proposer_index].pubkey, message_hash=signing_root(block), 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), ) return True @@ -347,7 +354,7 @@ def is_valid_shard_attestation(valid_shard_blocks: List[ShardBlock], (block for block in valid_shard_blocks if signing_root(block) == candidate.data.shard_block_root), None, ) - assert shard_block != None + assert shard_block is not None assert shard_block.slot == candidate.data.slot assert shard_block.shard == candidate.data.shard @@ -384,13 +391,14 @@ def is_valid_beacon_attestation(shard: Shard, else: previous_attestation = next( (attestation for attestation in valid_attestations if - attestation.data.crosslink.data_root == candidate.data.previous_crosslink.data_root) - , None) - assert previous_attestation != None + attestation.data.crosslink.data_root == candidate.data.previous_crosslink.data_root), + None, + ) + assert previous_attestation is not None assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot) # Check crosslink data root - start_epoch = state.latest_crosslinks[shard].epoch + start_epoch = beacon_state.latest_crosslinks[shard].epoch end_epoch = min(slot_to_epoch(candidate.data.slot) - CROSSLINK_LOOKBACK, start_epoch + MAX_EPOCHS_PER_CROSSLINK) blocks = [] for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH): From fd05b6e364d2622562a9587631d7bb5f83886eb0 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Tue, 28 May 2019 09:58:51 +0200 Subject: [PATCH 34/55] Minor bugfixes --- scripts/build_spec.py | 1 + specs/core/1_shard-data-chains.md | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index a1d390a95..c359dd08c 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -40,6 +40,7 @@ from eth2spec.utils.minimal_ssz import ( signing_root, type_of, empty, + serialize, ) from eth2spec.utils.bls_stub import ( diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index f26b220d7..2d6d2a407 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -145,7 +145,7 @@ def get_period_committee(state: BeaconState, ```python def get_switchover_epoch(state: BeaconState, epoch: Epoch, index: ValidatorIndex): earlier_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2 - return (bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + bytes3(index))[0:8]) + return (bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + int_to_bytes(index, length=3)[0:8])) % PERSISTENT_COMMITTEE_PERIOD) ``` @@ -255,11 +255,16 @@ def compute_crosslink_data_root(blocks: List[ShardBlock]) -> Bytes32: def hash_tree_root_of_bytes(data: bytes) -> bytes: return hash_tree_root([data[i:i + 32] for i in range(0, len(data), 32)]) + def zpad(data: bytes, length: int) -> bytes: + return data + b'\x00' * (length - len(data)) + return hash( hash_tree_root(pad_to_power_of_2([ - hash_tree_root_of_bytes(zpad(serialize(get_shard_header(block)), BYTES_PER_SHARD_BLOCK_BODY)) for block in blocks - ])) + - hash_tree_root(pad_to_power_of_2([ + hash_tree_root_of_bytes( + zpad(serialize(get_shard_header(block)), BYTES_PER_SHARD_BLOCK_BODY) + ) for block in blocks + ])) + + hash_tree_root(pad_to_power_of_2([ hash_tree_root_of_bytes(block.body) for block in blocks ])) ) From ed71efc061954fb87871fa60824ad236e08b7f40 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 10:41:39 +0200 Subject: [PATCH 35/55] state is kwarg --- .../test_process_proposer_slashing.py | 4 ++-- test_libs/pyspec/eth2spec/test/context.py | 17 ++++++++++------- .../epoch_processing/test_process_crosslinks.py | 6 ++---- .../test_process_registry_updates.py | 10 +++++----- .../eth2spec/test/helpers/attestations.py | 1 + 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py index b35241859..47f9ed1de 100644 --- a/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py @@ -40,17 +40,17 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True) ) -@with_all_phases @spec_state_test +@with_all_phases def test_success(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing) -@with_all_phases @always_bls @spec_state_test +@with_all_phases def test_invalid_sig_1(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 6b92f2151..dcdd8140b 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -4,10 +4,14 @@ from eth2spec.utils import bls from .helpers.genesis import create_genesis_state -from .utils import spectest, with_args, with_tags +from .utils import spectest, with_tags -# Provides a genesis state as first argument to the function decorated with this -with_state = with_args(lambda: [create_genesis_state(spec.SLOTS_PER_EPOCH * 8)]) + +def with_state(fn): + def entry(*args, **kw): + kw['state'] = create_genesis_state(spec=spec_phase0, num_validators=spec_phase0.SLOTS_PER_EPOCH * 8) + return fn(*args, **kw) + return entry # BLS is turned off by default *for performance purposes during TESTING*. @@ -88,18 +92,17 @@ def with_phase0(fn): Decorator to use phase 0's spec and helpers """ def entry(*args, **kw): - args = (spec_phase0, *args) - print(args) + kw['spec'] = spec_phase0 return fn(*args, **kw) return entry def with_phase1(fn): """ - Decorator to use phase 0's spec and helpers + Decorator to use phase 1's spec and helpers """ def entry(*args, **kw): - args = (spec_phase1, *args) + kw['spec'] = spec_phase1 return fn(*args, **kw) return entry diff --git a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py index 54e8d5ef2..65d958678 100644 --- a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py @@ -24,13 +24,13 @@ def run_process_crosslinks(spec, state, valid=True): """ # transition state to slot before state transition slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 - block = build_empty_block_for_next_slot(state) + block = build_empty_block_for_next_slot(spec, state) block.slot = slot sign_block(spec, state, block) spec.state_transition(state, block) # cache state before epoch transition - spec.spec.process_slot(state) + spec.process_slot(state) yield 'pre', state spec.process_crosslinks(state) @@ -91,7 +91,6 @@ def test_single_crosslink_update_from_previous_epoch(spec, state): # ensure rewarded for index in spec.get_crosslink_committee( - spec, state, attestation.data.target_epoch, attestation.data.crosslink.shard): @@ -144,7 +143,6 @@ def test_double_late_crosslink(spec, state): assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink for index in spec.get_crosslink_committee( - spec, state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): diff --git a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py index a3249a406..e6679f844 100644 --- a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py @@ -35,13 +35,13 @@ def run_process_registry_updates(spec, state, valid=True): @spec_state_test def test_activation(spec, state): index = 0 - assert spec.is_active_validator(state.validator_registry[index], spec.spec.get_current_epoch(state)) + assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) # Mock a new deposit state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE - assert not spec.is_active_validator(state.validator_registry[index], spec.spec.get_current_epoch(state)) + assert not spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): next_epoch(spec, state) @@ -52,7 +52,7 @@ def test_activation(spec, state): assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH assert spec.is_active_validator( state.validator_registry[index], - spec.spec.get_current_epoch(state), + spec.get_current_epoch(state), ) @@ -60,7 +60,7 @@ def test_activation(spec, state): @spec_state_test def test_ejection(spec, state): index = 0 - assert spec.is_active_validator(state.validator_registry[index], spec.spec.get_current_epoch(state)) + assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH # Mock an ejection @@ -74,5 +74,5 @@ def test_ejection(spec, state): assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH assert not spec.is_active_validator( state.validator_registry[index], - spec.spec.get_current_epoch(state), + spec.get_current_epoch(state), ) diff --git a/test_libs/pyspec/eth2spec/test/helpers/attestations.py b/test_libs/pyspec/eth2spec/test/helpers/attestations.py index a4eac3fb7..369738ed4 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/attestations.py +++ b/test_libs/pyspec/eth2spec/test/helpers/attestations.py @@ -89,6 +89,7 @@ def sign_aggregate_attestation(spec, state, attestation_data, participants: List privkey = privkeys[validator_index] signatures.append( get_attestation_signature( + spec, state, attestation_data, privkey From ec9f8f15ed7c11c637f4ea7addd8f764093a9457 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 11:32:53 +0200 Subject: [PATCH 36/55] Adds Custody Tests --- ...est_process_early_derived_secret_reveal.py | 122 ++++++++++++++++++ .../pyspec/eth2spec/test/helpers/custody.py | 38 ++++++ 2 files changed, 160 insertions(+) create mode 100644 test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py create mode 100644 test_libs/pyspec/eth2spec/test/helpers/custody.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py new file mode 100644 index 000000000..0f9057bb6 --- /dev/null +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py @@ -0,0 +1,122 @@ +from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal +from eth2spec.test.context import with_phase1, spec_state_test, expect_assertion_error + + +def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, valid=True): + """ + Run ``process_randao_key_reveal``, yielding: + - pre-state ('pre') + - randao_key_reveal ('randao_key_reveal') + - post-state ('post'). + If ``valid == False``, run expecting ``AssertionError`` + """ + yield 'pre', state + yield 'randao_key_reveal', randao_key_reveal + + if not valid: + expect_assertion_error(lambda: spec.process_early_derived_secret_reveal(state, randao_key_reveal)) + yield 'post', None + return + + spec.process_early_derived_secret_reveal(state, randao_key_reveal) + + slashed_validator = state.validator_registry[randao_key_reveal.revealed_index] + + if randao_key_reveal.epoch >= spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING: + assert slashed_validator.slashed + assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH + assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH + # lost whistleblower reward + # FIXME: Currently broken because get_base_reward in genesis epoch is 0 + assert ( + state.balances[randao_key_reveal.revealed_index] < + state.balances[randao_key_reveal.revealed_index] + ) + yield 'post', state + + +@with_phase1 +@spec_state_test +def test_success(spec, state): + randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state) + + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal) + + +@with_phase1 +@spec_state_test +def test_reveal_from_current_epoch(spec, state): + randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state)) + + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) + + +# @with_phase1 +# @spec_state_test +# def test_reveal_from_past_epoch(state): +# randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state) - 1) +# +# yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) + + +@with_phase1 +@spec_state_test +def test_reveal_with_custody_padding(spec, state): + randao_key_reveal = get_valid_early_derived_secret_reveal( + spec, + state, + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING, + ) + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) + + +@with_phase1 +@spec_state_test +def test_reveal_with_custody_padding_minus_one(spec, state): + randao_key_reveal = get_valid_early_derived_secret_reveal( + spec, + state, + spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1, + ) + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) + + +# @with_phase1 +# @spec_state_test +# def test_double_reveal(spec, state): +# randao_key_reveal1 = get_valid_early_derived_secret_reveal( +# spec, +# state, +# spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1, +# ) +# pre_state, intermediate_state = run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal1) + +# randao_key_reveal2 = get_valid_early_derived_secret_reveal( +# spec, +# intermediate_state, +# spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, +# ) +# _, post_state = run_early_derived_secret_reveal_processing(spec, intermediate_state, randao_key_reveal2, False) + +# return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + + +@with_phase1 +@spec_state_test +def test_revealer_is_slashed(spec, 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 + + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) + + +@with_phase1 +@spec_state_test +def test_far_future_epoch(spec, state): + randao_key_reveal = get_valid_early_derived_secret_reveal( + spec, + state, + spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, + ) + + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) diff --git a/test_libs/pyspec/eth2spec/test/helpers/custody.py b/test_libs/pyspec/eth2spec/test/helpers/custody.py new file mode 100644 index 000000000..67df12fcd --- /dev/null +++ b/test_libs/pyspec/eth2spec/test/helpers/custody.py @@ -0,0 +1,38 @@ +from eth2spec.test.helpers.keys import privkeys +from eth2spec.utils.bls import bls_sign + + +def get_valid_early_derived_secret_reveal(spec, state, epoch=None): + current_epoch = spec.get_current_epoch(state) + revealed_index = spec.get_active_validator_indices(state, current_epoch)[-1] + masker_index = spec.get_active_validator_indices(state, current_epoch)[0] + + if epoch is None: + epoch = current_epoch + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING + + reveal = bls_sign( + message_hash=spec.hash_tree_root(epoch), + privkey=privkeys[revealed_index], + domain=spec.get_domain( + state=state, + domain_type=spec.DOMAIN_RANDAO, + message_epoch=epoch, + ), + ) + mask = bls_sign( + message_hash=spec.hash_tree_root(epoch), + privkey=privkeys[masker_index], + domain=spec.get_domain( + state=state, + domain_type=spec.DOMAIN_RANDAO, + message_epoch=epoch, + ), + ) + + return spec.EarlyDerivedSecretReveal( + revealed_index=revealed_index, + epoch=epoch, + reveal=reveal, + masker_index=masker_index, + mask=mask, + ) From 0c57cfcaa7b62191ad327121a440c288ad930668 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 11:33:47 +0200 Subject: [PATCH 37/55] state builds from spec version --- .../test_process_proposer_slashing.py | 4 +- test_libs/pyspec/eth2spec/test/context.py | 5 +- ...est_process_early_derived_secret_reveal.py | 116 ------------------ 3 files changed, 6 insertions(+), 119 deletions(-) delete mode 100644 test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py index 47f9ed1de..b35241859 100644 --- a/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py @@ -40,17 +40,17 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True) ) -@spec_state_test @with_all_phases +@spec_state_test def test_success(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing) +@with_all_phases @always_bls @spec_state_test -@with_all_phases def test_invalid_sig_1(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=True) yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index dcdd8140b..d0869ba68 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -9,7 +9,10 @@ from .utils import spectest, with_tags def with_state(fn): def entry(*args, **kw): - kw['state'] = create_genesis_state(spec=spec_phase0, num_validators=spec_phase0.SLOTS_PER_EPOCH * 8) + try: + kw['state'] = create_genesis_state(spec=kw['spec'], num_validators=spec_phase0.SLOTS_PER_EPOCH * 8) + except KeyError: + raise TypeError('Spec decorator must come before state decorator to inject spec into state.') return fn(*args, **kw) return entry diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py deleted file mode 100644 index ad436ff29..000000000 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_process_early_derived_secret_reveal.py +++ /dev/null @@ -1,116 +0,0 @@ -from copy import deepcopy -import pytest - -# mark entire file as 'randao_key_reveals' -pytestmark = pytest.mark.randao_key_reveals - - -def run_early_derived_secret_reveal_processing(state, randao_key_reveal, valid=True): - """ - Run ``process_randao_key_reveal`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_early_derived_secret_reveal(post_state, randao_key_reveal) - return state, None - - spec.process_early_derived_secret_reveal(post_state, randao_key_reveal) - - slashed_validator = post_state.validator_registry[randao_key_reveal.revealed_index] - - if randao_key_reveal.epoch >= spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING: - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - # FIXME: Currently broken because get_base_reward in genesis epoch is 0 - assert ( - post_state.balances[randao_key_reveal.revealed_index] < - state.balances[randao_key_reveal.revealed_index] - ) - - return state, post_state - - -def test_success(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal) - - return pre_state, randao_key_reveal, post_state - - -def test_reveal_from_current_epoch(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - - -@pytest.mark.skip(reason="Not currently possible as we are testing at epoch 0") -def test_reveal_from_past_epoch(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state) - 1) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - - -def test_reveal_with_custody_padding(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( - state, - spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING, - ) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - - -def test_reveal_with_custody_padding_minus_one(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( - state, - spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - 1, - ) - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, True) - - return pre_state, randao_key_reveal, post_state - - -def test_double_reveal(state): - randao_key_reveal1 = helpers.get_valid_early_derived_secret_reveal( - state, - spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1, - ) - pre_state, intermediate_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal1) - - randao_key_reveal2 = helpers.get_valid_early_derived_secret_reveal( - intermediate_state, - spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, - ) - _, post_state = run_early_derived_secret_reveal_processing(intermediate_state, randao_key_reveal2, False) - - return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state - - -def test_revealer_is_slashed(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal(state, spec.get_current_epoch(state)) - state.validator_registry[randao_key_reveal.revealed_index].slashed = True - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state - - -def test_far_future_epoch(state): - randao_key_reveal = helpers.get_valid_early_derived_secret_reveal( - state, - spec.get_current_epoch(state) + spec.EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS, - ) - - pre_state, post_state = run_early_derived_secret_reveal_processing(state, randao_key_reveal, False) - - return pre_state, randao_key_reveal, post_state From 9e8a969f22dc187932a3c4f9ba8d8f68d467f0d1 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 12:44:34 +0200 Subject: [PATCH 38/55] Removes old tests & fixes phase1 tests --- Makefile | 9 +- ...est_process_early_derived_secret_reveal.py | 45 +- test_libs/pyspec/eth2spec/test/conftest.py | 2 +- test_libs/pyspec/tests/phase0/__init__.py | 0 .../test_process_attestation.py | 180 -------- .../test_process_attester_slashing.py | 107 ----- .../test_process_block_header.py | 65 --- .../block_processing/test_process_deposit.py | 128 ------ .../test_process_proposer_slashing.py | 87 ---- .../block_processing/test_process_transfer.py | 132 ------ .../block_processing/test_voluntary_exit.py | 150 ------- test_libs/pyspec/tests/phase0/conftest.py | 37 -- .../test_process_crosslinks.py | 201 --------- .../test_process_registry_updates.py | 104 ----- test_libs/pyspec/tests/phase0/helpers.py | 400 ----------------- .../pyspec/tests/phase0/test_finality.py | 234 ---------- test_libs/pyspec/tests/phase0/test_sanity.py | 402 ------------------ test_libs/pyspec/tests/phase1/__init__.py | 0 .../test_phase0_block_processing.py | 7 - test_libs/pyspec/tests/phase1/conftest.py | 39 -- .../test_phase0_epoch_processing.py | 2 - test_libs/pyspec/tests/phase1/helpers.py | 39 -- .../pyspec/tests/phase1/test_finality.py | 4 - test_libs/pyspec/tests/phase1/test_sanity.py | 4 - 24 files changed, 26 insertions(+), 2352 deletions(-) delete mode 100644 test_libs/pyspec/tests/phase0/__init__.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py delete mode 100644 test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py delete mode 100644 test_libs/pyspec/tests/phase0/conftest.py delete mode 100644 test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py delete mode 100644 test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py delete mode 100644 test_libs/pyspec/tests/phase0/helpers.py delete mode 100644 test_libs/pyspec/tests/phase0/test_finality.py delete mode 100644 test_libs/pyspec/tests/phase0/test_sanity.py delete mode 100644 test_libs/pyspec/tests/phase1/__init__.py delete mode 100644 test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py delete mode 100644 test_libs/pyspec/tests/phase1/conftest.py delete mode 100644 test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py delete mode 100644 test_libs/pyspec/tests/phase1/helpers.py delete mode 100644 test_libs/pyspec/tests/phase1/test_finality.py delete mode 100644 test_libs/pyspec/tests/phase1/test_sanity.py diff --git a/Makefile b/Makefile index b80e81238..af71f44fb 100644 --- a/Makefile +++ b/Makefile @@ -43,8 +43,7 @@ test: $(PY_SPEC_ALL_TARGETS) citest: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); mkdir -p test-reports/eth2spec; . venv/bin/activate; \ - python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase0; \ - python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml tests/phase1 + python -m pytest --junitxml=test-reports/eth2spec/test_results_phase0.xml eth2spec install_lint: cd $(PY_SPEC_DIR); python3 -m venv venv; . venv/bin/activate; pip3 install flake8==3.5.0 @@ -57,12 +56,6 @@ lint: $(PY_SPEC_ALL_TARGETS) # "make pyspec" to create the pyspec for all phases. pyspec: $(PY_SPEC_ALL_TARGETS) -# "make phase0" to create pyspec for phase0 -phase0: $(PY_SPEC_PHASE_0_TARGETS) - -# "make phase1" to create pyspec for phase1 -phase1: $(PY_SPEC_PHASE_1_TARGETS) - $(PY_SPEC_PHASE_0_TARGETS): $(PY_SPEC_PHASE_0_DEPS) python3 $(SCRIPT_DIR)/build_spec.py -p0 $(SPEC_DIR)/core/0_beacon-chain.md $@ diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py index 0f9057bb6..4b4608d4d 100644 --- a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py @@ -28,10 +28,10 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward # FIXME: Currently broken because get_base_reward in genesis epoch is 0 - assert ( - state.balances[randao_key_reveal.revealed_index] < - state.balances[randao_key_reveal.revealed_index] - ) + # assert ( + # state.balances[randao_key_reveal.revealed_index] < + # state.balances[randao_key_reveal.revealed_index] + # ) yield 'post', state @@ -81,24 +81,27 @@ def test_reveal_with_custody_padding_minus_one(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) -# @with_phase1 -# @spec_state_test -# def test_double_reveal(spec, state): -# randao_key_reveal1 = get_valid_early_derived_secret_reveal( -# spec, -# state, -# spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1, -# ) -# pre_state, intermediate_state = run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal1) +@with_phase1 +@spec_state_test +def test_double_reveal(spec, state): + randao_key_reveal1 = get_valid_early_derived_secret_reveal( + spec, + state, + spec.get_current_epoch(state) + spec.RANDAO_PENALTY_EPOCHS + 1, + ) + res = dict(run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal1)) + pre_state = res['pre'] + yield 'pre', pre_state + intermediate_state = res['post'] -# randao_key_reveal2 = get_valid_early_derived_secret_reveal( -# spec, -# intermediate_state, -# spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, -# ) -# _, post_state = run_early_derived_secret_reveal_processing(spec, intermediate_state, randao_key_reveal2, False) - -# return pre_state, [randao_key_reveal1, randao_key_reveal2], post_state + randao_key_reveal2 = get_valid_early_derived_secret_reveal( + spec, + intermediate_state, + spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, + ) + post_state = dict(run_early_derived_secret_reveal_processing(spec, intermediate_state, randao_key_reveal2, False))['post'] + yield 'randao_key_reveal', [randao_key_reveal1, randao_key_reveal2] + yield 'post', post_state @with_phase1 diff --git a/test_libs/pyspec/eth2spec/test/conftest.py b/test_libs/pyspec/eth2spec/test/conftest.py index b2acb0573..5713c3470 100644 --- a/test_libs/pyspec/eth2spec/test/conftest.py +++ b/test_libs/pyspec/eth2spec/test/conftest.py @@ -1,5 +1,5 @@ from eth2spec.phase0 import spec as spec_phase0 -from eth2spec.phase0 import spec as spec_phase1 +from eth2spec.phase1 import spec as spec_phase1 # We import pytest only when it's present, i.e. when we are running tests. # The test-cases themselves can be generated without installing pytest. diff --git a/test_libs/pyspec/tests/phase0/__init__.py b/test_libs/pyspec/tests/phase0/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py deleted file mode 100644 index 122195fc1..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attestation.py +++ /dev/null @@ -1,180 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'attestations' -pytestmark = pytest.mark.attestations - - -def run_attestation_processing(state, attestation, valid=True): - """ - Run ``spec.process_attestation`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_attestation(post_state, attestation) - return state, None - - spec.process_attestation(post_state, attestation) - - current_epoch = spec.get_current_epoch(state) - if attestation.data.target_epoch == current_epoch: - assert len(post_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1 - else: - assert len(post_state.previous_epoch_attestations) == len(state.previous_epoch_attestations) + 1 - - return state, post_state - - -def test_success(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - pre_state, post_state = run_attestation_processing(state, attestation) - - return pre_state, attestation, post_state - - -def test_success_prevous_epoch(state): - attestation = helpers.get_valid_attestation(state) - block = helpers.build_empty_block_for_next_slot(state) - block.slot = state.slot + spec.SLOTS_PER_EPOCH - spec.state_transition(state, block) - - pre_state, post_state = run_attestation_processing(state, attestation) - - return pre_state, attestation, post_state - - -def test_success_since_max_epochs_per_crosslink(state): - for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): - helpers.next_epoch(state) - - attestation = helpers.get_valid_attestation(state) - data = attestation.data - assert data.crosslink.end_epoch - data.crosslink.start_epoch == spec.MAX_EPOCHS_PER_CROSSLINK - - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - helpers.next_slot(state) - - pre_state, post_state = run_attestation_processing(state, attestation) - - return pre_state, attestation, post_state - - -def test_before_inclusion_delay(state): - attestation = helpers.get_valid_attestation(state) - # do not increment slot to allow for inclusion delay - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_after_epoch_slots(state): - attestation = helpers.get_valid_attestation(state) - block = helpers.build_empty_block_for_next_slot(state) - # increment past latest inclusion slot - block.slot = state.slot + spec.SLOTS_PER_EPOCH + 1 - spec.state_transition(state, block) - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_bad_source_epoch(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.data.source_epoch += 10 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_bad_source_root(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.data.source_root = b'\x42' * 32 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_non_zero_crosslink_data_root(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.data.crosslink.data_root = b'\x42' * 32 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_bad_previous_crosslink(state): - helpers.next_epoch(state) - attestation = helpers.get_valid_attestation(state) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - helpers.next_slot(state) - - attestation.data.crosslink.parent_root = b'\x27' * 32 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_bad_crosslink_start_epoch(state): - helpers.next_epoch(state) - attestation = helpers.get_valid_attestation(state) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - helpers.next_slot(state) - - attestation.data.crosslink.start_epoch += 1 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_bad_crosslink_end_epoch(state): - helpers.next_epoch(state) - attestation = helpers.get_valid_attestation(state) - for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): - helpers.next_slot(state) - - attestation.data.crosslink.end_epoch += 1 - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_non_empty_custody_bitfield(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) - - pre_state, post_state = run_attestation_processing(state, attestation, False) - - return pre_state, attestation, post_state - - -def test_empty_aggregation_bitfield(state): - attestation = helpers.get_valid_attestation(state) - state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - - attestation.aggregation_bitfield = b'\x00' * len(attestation.aggregation_bitfield) - - pre_state, post_state = run_attestation_processing(state, attestation) - - return pre_state, attestation, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py deleted file mode 100644 index 66617fd6d..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_attester_slashing.py +++ /dev/null @@ -1,107 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'attester_slashing' -pytestmark = pytest.mark.attester_slashings - - -def run_attester_slashing_processing(state, attester_slashing, valid=True): - """ - Run ``spec.process_attester_slashing`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_attester_slashing(post_state, attester_slashing) - return state, None - - spec.process_attester_slashing(post_state, attester_slashing) - - slashed_index = attester_slashing.attestation_1.custody_bit_0_indices[0] - slashed_validator = post_state.validator_registry[slashed_index] - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - assert ( - helpers.get_balance(post_state, slashed_index) < - helpers.get_balance(state, slashed_index) - ) - proposer_index = spec.get_beacon_proposer_index(state) - # gained whistleblower reward - assert ( - helpers.get_balance(post_state, proposer_index) > - helpers.get_balance(state, proposer_index) - ) - - return state, post_state - - -def test_success_double(state): - attester_slashing = helpers.get_valid_attester_slashing(state) - - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) - - return pre_state, attester_slashing, post_state - - -def test_success_surround(state): - helpers.next_epoch(state) - state.current_justified_epoch += 1 - attester_slashing = helpers.get_valid_attester_slashing(state) - - # set attestion1 to surround attestation 2 - attester_slashing.attestation_1.data.source_epoch = attester_slashing.attestation_2.data.source_epoch - 1 - attester_slashing.attestation_1.data.target_epoch = attester_slashing.attestation_2.data.target_epoch + 1 - - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing) - - return pre_state, attester_slashing, post_state - - -def test_same_data(state): - attester_slashing = helpers.get_valid_attester_slashing(state) - - attester_slashing.attestation_1.data = attester_slashing.attestation_2.data - - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) - - return pre_state, attester_slashing, post_state - - -def test_no_double_or_surround(state): - attester_slashing = helpers.get_valid_attester_slashing(state) - - attester_slashing.attestation_1.data.target_epoch += 1 - - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) - - return pre_state, attester_slashing, post_state - - -def test_participants_already_slashed(state): - attester_slashing = helpers.get_valid_attester_slashing(state) - - # set all indices to slashed - attestation_1 = attester_slashing.attestation_1 - validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices - for index in validator_indices: - state.validator_registry[index].slashed = True - - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) - - return pre_state, attester_slashing, post_state - - -def test_custody_bit_0_and_1(state): - attester_slashing = helpers.get_valid_attester_slashing(state) - - attester_slashing.attestation_1.custody_bit_1_indices = ( - attester_slashing.attestation_1.custody_bit_0_indices - ) - pre_state, post_state = run_attester_slashing_processing(state, attester_slashing, False) - - return pre_state, attester_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py deleted file mode 100644 index f7032a283..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_block_header.py +++ /dev/null @@ -1,65 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'header' -pytestmark = pytest.mark.header - - -def prepare_state_for_header_processing(state): - spec.process_slot(state) - helpers.advance_slot(state) - - -def run_block_header_processing(state, block, valid=True): - """ - Run ``spec.process_block_header`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - prepare_state_for_header_processing(state) - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_block_header(post_state, block) - return state, None - - spec.process_block_header(post_state, block) - return state, post_state - - -def test_success(state): - block = helpers.build_empty_block_for_next_slot(state) - pre_state, post_state = run_block_header_processing(state, block) - return state, block, post_state - - -def test_invalid_slot(state): - block = helpers.build_empty_block_for_next_slot(state) - block.slot = state.slot + 2 # invalid slot - - pre_state, post_state = run_block_header_processing(state, block, valid=False) - return pre_state, block, None - - -def test_invalid_parent_block_root(state): - block = helpers.build_empty_block_for_next_slot(state) - block.parent_root = b'\12' * 32 # invalid prev root - - pre_state, post_state = run_block_header_processing(state, block, valid=False) - return pre_state, block, None - - -def test_proposer_slashed(state): - # use stub state to get proposer index of next slot - stub_state = deepcopy(state) - helpers.next_slot(stub_state) - proposer_index = spec.get_beacon_proposer_index(stub_state) - - # set proposer to slashed - state.validator_registry[proposer_index].slashed = True - - block = helpers.build_empty_block_for_next_slot(state) - - pre_state, post_state = run_block_header_processing(state, block, valid=False) - return pre_state, block, None diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py deleted file mode 100644 index f3abab354..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_deposit.py +++ /dev/null @@ -1,128 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'deposits' -pytestmark = pytest.mark.deposits - - -def test_success(state): - pre_state = deepcopy(state) - # fill previous deposits with zero-hash - deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - index = len(deposit_data_leaves) - pubkey = helpers.pubkeys[index] - privkey = helpers.privkeys[index] - deposit, root, deposit_data_leaves = helpers.build_deposit( - pre_state, - deposit_data_leaves, - pubkey, - privkey, - spec.MAX_EFFECTIVE_BALANCE, - ) - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves) - - post_state = deepcopy(pre_state) - - spec.process_deposit(post_state, deposit) - - assert len(post_state.validator_registry) == len(state.validator_registry) + 1 - assert len(post_state.balances) == len(state.balances) + 1 - assert post_state.validator_registry[index].pubkey == helpers.pubkeys[index] - assert helpers.get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE - assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count - - return pre_state, deposit, post_state - - -def test_success_top_up(state): - pre_state = deepcopy(state) - deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - validator_index = 0 - amount = spec.MAX_EFFECTIVE_BALANCE // 4 - pubkey = helpers.pubkeys[validator_index] - privkey = helpers.privkeys[validator_index] - deposit, root, deposit_data_leaves = helpers.build_deposit( - pre_state, - deposit_data_leaves, - pubkey, - privkey, - amount, - ) - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves) - pre_balance = helpers.get_balance(pre_state, validator_index) - - post_state = deepcopy(pre_state) - - spec.process_deposit(post_state, deposit) - - assert len(post_state.validator_registry) == len(state.validator_registry) - assert len(post_state.balances) == len(state.balances) - assert post_state.deposit_index == post_state.latest_eth1_data.deposit_count - assert helpers.get_balance(post_state, validator_index) == pre_balance + amount - - return pre_state, deposit, post_state - - -def test_wrong_index(state): - pre_state = deepcopy(state) - deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - index = len(deposit_data_leaves) - pubkey = helpers.pubkeys[index] - privkey = helpers.privkeys[index] - deposit, root, deposit_data_leaves = helpers.build_deposit( - pre_state, - deposit_data_leaves, - pubkey, - privkey, - spec.MAX_EFFECTIVE_BALANCE, - ) - - # mess up deposit_index - deposit.index = pre_state.deposit_index + 1 - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves) - - post_state = deepcopy(pre_state) - - with pytest.raises(AssertionError): - spec.process_deposit(post_state, deposit) - - return pre_state, deposit, None - - -def test_bad_merkle_proof(state): - pre_state = deepcopy(state) - deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - index = len(deposit_data_leaves) - pubkey = helpers.pubkeys[index] - privkey = helpers.privkeys[index] - deposit, root, deposit_data_leaves = helpers.build_deposit( - pre_state, - deposit_data_leaves, - pubkey, - privkey, - spec.MAX_EFFECTIVE_BALANCE, - ) - - # mess up merkle branch - deposit.proof[-1] = spec.ZERO_HASH - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(deposit_data_leaves) - - post_state = deepcopy(pre_state) - - with pytest.raises(AssertionError): - spec.process_deposit(post_state, deposit) - - return pre_state, deposit, None diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py deleted file mode 100644 index f97eb1584..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_proposer_slashing.py +++ /dev/null @@ -1,87 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'proposer_slashings' -pytestmark = pytest.mark.proposer_slashings - - -def run_proposer_slashing_processing(state, proposer_slashing, valid=True): - """ - Run ``spec.process_proposer_slashing`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_proposer_slashing(post_state, proposer_slashing) - return state, None - - spec.process_proposer_slashing(post_state, proposer_slashing) - - slashed_validator = post_state.validator_registry[proposer_slashing.proposer_index] - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - assert ( - helpers.get_balance(post_state, proposer_slashing.proposer_index) < - helpers.get_balance(state, proposer_slashing.proposer_index) - ) - - return state, post_state - - -def test_success(state): - proposer_slashing = helpers.get_valid_proposer_slashing(state) - - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing) - - return pre_state, proposer_slashing, post_state - - -def test_epochs_are_different(state): - proposer_slashing = helpers.get_valid_proposer_slashing(state) - - # set slots to be in different epochs - proposer_slashing.header_2.slot += spec.SLOTS_PER_EPOCH - - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) - - return pre_state, proposer_slashing, post_state - - -def test_headers_are_same(state): - proposer_slashing = helpers.get_valid_proposer_slashing(state) - - # set headers to be the same - proposer_slashing.header_2 = proposer_slashing.header_1 - - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) - - return pre_state, proposer_slashing, post_state - - -def test_proposer_is_slashed(state): - proposer_slashing = helpers.get_valid_proposer_slashing(state) - - # set proposer to slashed - state.validator_registry[proposer_slashing.proposer_index].slashed = True - - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) - - return pre_state, proposer_slashing, post_state - - -def test_proposer_is_withdrawn(state): - proposer_slashing = helpers.get_valid_proposer_slashing(state) - - # set proposer withdrawable_epoch in past - current_epoch = spec.get_current_epoch(state) - proposer_index = proposer_slashing.proposer_index - state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1 - - pre_state, post_state = run_proposer_slashing_processing(state, proposer_slashing, False) - - return pre_state, proposer_slashing, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py b/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py deleted file mode 100644 index 6c57c54f0..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_process_transfer.py +++ /dev/null @@ -1,132 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'transfers' -pytestmark = pytest.mark.transfers - - -def run_transfer_processing(state, transfer, valid=True): - """ - Run ``spec.process_transfer`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_transfer(post_state, transfer) - return state, None - - spec.process_transfer(post_state, transfer) - - proposer_index = spec.get_beacon_proposer_index(state) - pre_transfer_sender_balance = state.balances[transfer.sender] - pre_transfer_recipient_balance = state.balances[transfer.recipient] - pre_transfer_proposer_balance = state.balances[proposer_index] - sender_balance = post_state.balances[transfer.sender] - recipient_balance = post_state.balances[transfer.recipient] - assert sender_balance == pre_transfer_sender_balance - transfer.amount - transfer.fee - assert recipient_balance == pre_transfer_recipient_balance + transfer.amount - assert post_state.balances[proposer_index] == pre_transfer_proposer_balance + transfer.fee - - return state, post_state - - -def test_success_non_activated(state): - transfer = helpers.get_valid_transfer(state) - # un-activate so validator can transfer - state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - - pre_state, post_state = run_transfer_processing(state, transfer) - - return pre_state, transfer, post_state - - -def test_success_withdrawable(state): - helpers.next_epoch(state) - - transfer = helpers.get_valid_transfer(state) - - # withdrawable_epoch in past so can transfer - state.validator_registry[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1 - - pre_state, post_state = run_transfer_processing(state, transfer) - - return pre_state, transfer, post_state - - -def test_success_active_above_max_effective(state): - sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] - amount = spec.MAX_EFFECTIVE_BALANCE // 32 - state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE + amount - transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - - pre_state, post_state = run_transfer_processing(state, transfer) - - return pre_state, transfer, post_state - - -def test_active_but_transfer_past_effective_balance(state): - sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] - amount = spec.MAX_EFFECTIVE_BALANCE // 32 - state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE - transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount, fee=0) - - pre_state, post_state = run_transfer_processing(state, transfer, False) - - return pre_state, transfer, post_state - - -def test_incorrect_slot(state): - transfer = helpers.get_valid_transfer(state, slot=state.slot + 1) - # un-activate so validator can transfer - state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - - pre_state, post_state = run_transfer_processing(state, transfer, False) - - return pre_state, transfer, post_state - - -def test_insufficient_balance(state): - sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] - amount = spec.MAX_EFFECTIVE_BALANCE - state.balances[sender_index] = spec.MAX_EFFECTIVE_BALANCE - transfer = helpers.get_valid_transfer(state, sender_index=sender_index, amount=amount + 1, fee=0) - - # un-activate so validator can transfer - state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - - pre_state, post_state = run_transfer_processing(state, transfer, False) - - return pre_state, transfer, post_state - - -def test_no_dust(state): - sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] - balance = state.balances[sender_index] - transfer = helpers.get_valid_transfer( - state, - sender_index=sender_index, - amount=balance - spec.MIN_DEPOSIT_AMOUNT + 1, - fee=0, - ) - - # un-activate so validator can transfer - state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - - pre_state, post_state = run_transfer_processing(state, transfer, False) - - return pre_state, transfer, post_state - - -def test_invalid_pubkey(state): - transfer = helpers.get_valid_transfer(state) - state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH - - # un-activate so validator can transfer - state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH - - pre_state, post_state = run_transfer_processing(state, transfer, False) - - return pre_state, transfer, post_state diff --git a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py b/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py deleted file mode 100644 index a3e54f00e..000000000 --- a/test_libs/pyspec/tests/phase0/block_processing/test_voluntary_exit.py +++ /dev/null @@ -1,150 +0,0 @@ -from copy import deepcopy -import pytest - - -# mark entire file as 'voluntary_exits' -pytestmark = pytest.mark.voluntary_exits - - -def run_voluntary_exit_processing(state, voluntary_exit, valid=True): - """ - Run ``spec.process_voluntary_exit`` returning the pre and post state. - If ``valid == False``, run expecting ``AssertionError`` - """ - post_state = deepcopy(state) - - if not valid: - with pytest.raises(AssertionError): - spec.process_voluntary_exit(post_state, voluntary_exit) - return state, None - - spec.process_voluntary_exit(post_state, voluntary_exit) - - validator_index = voluntary_exit.validator_index - assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH - assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH - - return state, post_state - - -def test_success(state): - # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit - state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] - privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - validator_index, - privkey, - ) - - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit) - return pre_state, voluntary_exit, post_state - - -def test_success_exit_queue(state): - # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit - state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - - current_epoch = spec.get_current_epoch(state) - - # exit `MAX_EXITS_PER_EPOCH` - initial_indices = spec.get_active_validator_indices(state, current_epoch)[:spec.get_churn_limit(state)] - post_state = state - for index in initial_indices: - privkey = helpers.pubkey_to_privkey[state.validator_registry[index].pubkey] - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - index, - privkey, - ) - - pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) - - # exit an additional validator - validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] - privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - validator_index, - privkey, - ) - - pre_state, post_state = run_voluntary_exit_processing(post_state, voluntary_exit) - - assert ( - post_state.validator_registry[validator_index].exit_epoch == - post_state.validator_registry[initial_indices[0]].exit_epoch + 1 - ) - - return pre_state, voluntary_exit, post_state - - -def test_validator_not_active(state): - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] - privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - - state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH - - # - # build and test voluntary exit - # - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - validator_index, - privkey, - ) - - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) - return pre_state, voluntary_exit, post_state - - -def test_validator_already_exited(state): - # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit - state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] - privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - - # but validator already has exited - state.validator_registry[validator_index].exit_epoch = current_epoch + 2 - - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - validator_index, - privkey, - ) - - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) - return pre_state, voluntary_exit, post_state - - -def test_validator_not_active_long_enough(state): - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[0] - privkey = helpers.pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - - voluntary_exit = helpers.build_voluntary_exit( - state, - current_epoch, - validator_index, - privkey, - ) - - assert ( - current_epoch - state.validator_registry[validator_index].activation_epoch < - spec.PERSISTENT_COMMITTEE_PERIOD - ) - - pre_state, post_state = run_voluntary_exit_processing(state, voluntary_exit, False) - return pre_state, voluntary_exit, post_state diff --git a/test_libs/pyspec/tests/phase0/conftest.py b/test_libs/pyspec/tests/phase0/conftest.py deleted file mode 100644 index 67dc34fa4..000000000 --- a/test_libs/pyspec/tests/phase0/conftest.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest - -from eth2spec.phase0 import spec -from preset_loader import loader - -from tests.phase0 import helpers - - -def pytest_addoption(parser): - parser.addoption( - "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" - ) - - -@pytest.fixture(autouse=True) -def config(request): - config_name = request.config.getoption("--config") - presets = loader.load_presets('../../configs/', config_name) - spec.apply_constants_preset(presets) - helpers.spec = spec - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers - - -@pytest.fixture -def num_validators(config): - return spec.SLOTS_PER_EPOCH * 8 - - -@pytest.fixture -def deposit_data_leaves(): - return list() - - -@pytest.fixture -def state(num_validators, deposit_data_leaves): - return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py deleted file mode 100644 index 644bef415..000000000 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py +++ /dev/null @@ -1,201 +0,0 @@ -from copy import deepcopy - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py -======= -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - process_slot, - get_crosslink_deltas, - process_crosslinks, - state_transition, -) -from eth2spec.test.context import spec_state_test -from eth2spec.test.helpers.state import ( - next_epoch, - next_slot -) -from eth2spec.test.helpers.block import apply_empty_block, sign_block -from eth2spec.test.helpers.attestations import ( - add_attestation_to_state, - build_empty_block_for_next_slot, - fill_aggregate_attestation, - get_crosslink_committee, - get_valid_attestation, - sign_attestation, -) - ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - -def run_process_crosslinks(state, valid=True): - """ - Run ``process_crosslinks``, yielding: - - pre-state ('pre') - - post-state ('post'). - If ``valid == False``, run expecting ``AssertionError`` - """ - # transition state to slot before state transition - slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 - block = helpers.build_empty_block_for_next_slot(state) - block.slot = slot -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - spec.state_transition(state, block) -======= - sign_block(state, block) - state_transition(state, block) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - # cache state before epoch transition - spec.process_slot(state) - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - post_state = deepcopy(state) - spec.process_crosslinks(post_state) - - return state, post_state -======= - yield 'pre', state - process_crosslinks(state) - yield 'post', state ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - -@spec_state_test -def test_no_attestations(state): - yield from run_process_crosslinks(state) - - for shard in range(spec.SHARD_COUNT): - assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] - - -@spec_state_test -def test_single_crosslink_update_from_current_epoch(state): - helpers.next_epoch(state) - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - attestation = helpers.get_valid_attestation(state) -======= - attestation = get_valid_attestation(state, signed=True) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - helpers.fill_aggregate_attestation(state, attestation) - helpers.add_attestation_to_state(state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) - - assert len(state.current_epoch_attestations) == 1 - - shard = attestation.data.crosslink.shard - pre_crosslink = deepcopy(state.current_crosslinks[shard]) - - yield from run_process_crosslinks(state) - - assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] - assert pre_crosslink != state.current_crosslinks[shard] - - -@spec_state_test -def test_single_crosslink_update_from_previous_epoch(state): - helpers.next_epoch(state) - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - attestation = helpers.get_valid_attestation(state) -======= - attestation = get_valid_attestation(state, signed=True) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - helpers.fill_aggregate_attestation(state, attestation) - helpers.add_attestation_to_state(state, attestation, state.slot + spec.SLOTS_PER_EPOCH) - - assert len(state.previous_epoch_attestations) == 1 - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - pre_state, post_state = run_process_crosslinks(state) - crosslink_deltas = spec.get_crosslink_deltas(state) -======= - shard = attestation.data.crosslink.shard - pre_crosslink = deepcopy(state.current_crosslinks[shard]) - - crosslink_deltas = get_crosslink_deltas(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - yield from run_process_crosslinks(state) - - assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] - assert pre_crosslink != state.current_crosslinks[shard] - - # ensure rewarded - for index in spec.get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): - assert crosslink_deltas[0][index] > 0 - assert crosslink_deltas[1][index] == 0 - - -@spec_state_test -def test_double_late_crosslink(state): -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - helpers.next_epoch(state) - state.slot += 4 - - attestation_1 = helpers.get_valid_attestation(state) - helpers.fill_aggregate_attestation(state, attestation_1) - - # add attestation_1 in the next epoch - helpers.next_epoch(state) - helpers.add_attestation_to_state(state, attestation_1, state.slot + 1) -======= - if spec.get_epoch_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: - print("warning: ignoring test, test-assumptions are incompatible with configuration") - return - - next_epoch(state) - state.slot += 4 - - attestation_1 = get_valid_attestation(state, signed=True) - fill_aggregate_attestation(state, attestation_1) - - # add attestation_1 to next epoch - next_epoch(state) - add_attestation_to_state(state, attestation_1, state.slot + 1) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - for slot in range(spec.SLOTS_PER_EPOCH): - attestation_2 = helpers.get_valid_attestation(state) - if attestation_2.data.crosslink.shard == attestation_1.data.crosslink.shard: - sign_attestation(state, attestation_2) - break -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - helpers.next_slot(state) - helpers.fill_aggregate_attestation(state, attestation_2) -======= - next_slot(state) - apply_empty_block(state) - - fill_aggregate_attestation(state, attestation_2) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - # add attestation_2 in the next epoch after attestation_1 has - # already updated the relevant crosslink - helpers.next_epoch(state) - helpers.add_attestation_to_state(state, attestation_2, state.slot + 1) - - assert len(state.previous_epoch_attestations) == 1 - assert len(state.current_epoch_attestations) == 0 - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_crosslinks.py - pre_state, post_state = run_process_crosslinks(state) - crosslink_deltas = spec.get_crosslink_deltas(state) -======= - crosslink_deltas = get_crosslink_deltas(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py - - yield from run_process_crosslinks(state) - - shard = attestation_2.data.crosslink.shard - - # ensure that the current crosslinks were not updated by the second attestation - assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] - # ensure no reward, only penalties for the failed crosslink - for index in spec.get_crosslink_committee( - state, - attestation_2.data.target_epoch, - attestation_2.data.crosslink.shard): - assert crosslink_deltas[0][index] == 0 - assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py deleted file mode 100644 index 4841fa616..000000000 --- a/test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py +++ /dev/null @@ -1,104 +0,0 @@ -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py -from copy import deepcopy -import pytest - - -# mark entire file as 'state' -pytestmark = pytest.mark.state - - -======= -import eth2spec.phase0.spec as spec - -from eth2spec.phase0.spec import ( - get_current_epoch, - is_active_validator, - process_registry_updates -) -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.state import next_epoch -from eth2spec.test.context import spec_state_test - - -def run_process_registry_updates(state, valid=True): - """ - Run ``process_crosslinks``, yielding: - - pre-state ('pre') - - post-state ('post'). - If ``valid == False``, run expecting ``AssertionError`` - """ - # transition state to slot before state transition - slot = state.slot + (spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) - 1 - block = build_empty_block_for_next_slot(state) - block.slot = slot - sign_block(state, block) - state_transition(state, block) - - # cache state before epoch transition - spec.process_slot(state) - - # process components of epoch transition before registry update - spec.process_justification_and_finalization(state) - spec.process_crosslinks(state) - spec.process_rewards_and_penalties(state) - - yield 'pre', state - process_registry_updates(state) - yield 'post', state - - -@spec_state_test ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py -def test_activation(state): - index = 0 - assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) - - # Mock a new deposit - state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH - state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE - assert not spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) - - for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py - block = helpers.next_epoch(state) - blocks.append(block) -======= - next_epoch(state) - - yield from run_process_registry_updates(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py - - assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH - assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH - assert spec.is_active_validator( - state.validator_registry[index], - spec.get_current_epoch(state), - ) - - -@spec_state_test -def test_ejection(state): - index = 0 - assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state)) - assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH - - # Mock an ejection - state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE - - for _ in range(spec.ACTIVATION_EXIT_DELAY + 1): -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/epoch_processing/test_process_registry_updates.py - block = helpers.next_epoch(state) - blocks.append(block) -======= - next_epoch(state) - - yield from run_process_registry_updates(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py - - assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH - assert not spec.is_active_validator( - state.validator_registry[index], - spec.get_current_epoch(state), - ) diff --git a/test_libs/pyspec/tests/phase0/helpers.py b/test_libs/pyspec/tests/phase0/helpers.py deleted file mode 100644 index 140f74a53..000000000 --- a/test_libs/pyspec/tests/phase0/helpers.py +++ /dev/null @@ -1,400 +0,0 @@ -from copy import deepcopy - -from py_ecc import bls - -from eth2spec.utils.minimal_ssz import signing_root -from eth2spec.utils.merkle_minimal import ( - calc_merkle_tree_from_leaves, - get_merkle_proof, - get_merkle_root, -) - -privkeys = [i + 1 for i in range(1024)] -pubkeys = [bls.privtopub(privkey) for privkey in privkeys] -pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} - - -def advance_slot(state) -> None: - state.slot += 1 - - -def get_balance(state, index): - return state.balances[index] - - -def set_bitfield_bit(bitfield, i): - """ - Set the bit in ``bitfield`` at position ``i`` to ``1``. - """ - byte_index = i // 8 - bit_index = i % 8 - return ( - bitfield[:byte_index] + - bytes([bitfield[byte_index] | (1 << bit_index)]) + - bitfield[byte_index + 1:] - ) - - -def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None): - if not deposit_data_leaves: - deposit_data_leaves = [] - signature = b'\x33' * 96 - - deposit_data_list = [] - for i in range(num_validators): - pubkey = pubkeys[i] - deposit_data = spec.DepositData( - pubkey=pubkey, - # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], - amount=spec.MAX_EFFECTIVE_BALANCE, - signature=signature, - ) - item = deposit_data.hash_tree_root() - deposit_data_leaves.append(item) - tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) - root = get_merkle_root((tuple(deposit_data_leaves))) - proof = list(get_merkle_proof(tree, item_index=i)) - assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, i, root) - deposit_data_list.append(deposit_data) - - genesis_validator_deposits = [] - for i in range(num_validators): - genesis_validator_deposits.append(spec.Deposit( - proof=list(get_merkle_proof(tree, item_index=i)), - index=i, - data=deposit_data_list[i] - )) - return genesis_validator_deposits, root - - -def create_genesis_state(num_validators, deposit_data_leaves=None): - initial_deposits, deposit_root = create_mock_genesis_validator_deposits( - num_validators, - deposit_data_leaves, - ) - return spec.get_genesis_beacon_state( - initial_deposits, - genesis_time=0, - genesis_eth1_data=spec.Eth1Data( - deposit_root=deposit_root, - deposit_count=len(initial_deposits), - block_hash=spec.ZERO_HASH, - ), - ) - - -def build_empty_block_for_next_slot(state): - empty_block = spec.BeaconBlock() - empty_block.slot = state.slot + 1 - empty_block.body.eth1_data.deposit_count = state.deposit_index - previous_block_header = deepcopy(state.latest_block_header) - if previous_block_header.state_root == spec.ZERO_HASH: - previous_block_header.state_root = state.hash_tree_root() - empty_block.parent_root = signing_root(previous_block_header) - return empty_block - - -def build_deposit_data(state, pubkey, privkey, amount): - deposit_data = spec.DepositData( - pubkey=pubkey, - # insecurely use pubkey as withdrawal key as well - withdrawal_credentials=spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:], - amount=amount, - ) - signature = bls.sign( - message_hash=signing_root(deposit_data), - privkey=privkey, - domain=spec.bls_domain(spec.DOMAIN_DEPOSIT), - ) - deposit_data.signature = signature - return deposit_data - - -def build_attestation_data(state, slot, shard): - assert state.slot >= slot - - if slot == state.slot: - block_root = build_empty_block_for_next_slot(state).parent_root - else: - block_root = spec.get_block_root_at_slot(state, slot) - - current_epoch_start_slot = spec.get_epoch_start_slot(spec.get_current_epoch(state)) - if slot < current_epoch_start_slot: - epoch_boundary_root = spec.get_block_root(state, spec.get_previous_epoch(state)) - elif slot == current_epoch_start_slot: - epoch_boundary_root = block_root - else: - epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state)) - - if slot < current_epoch_start_slot: - justified_epoch = state.previous_justified_epoch - justified_block_root = state.previous_justified_root - else: - justified_epoch = state.current_justified_epoch - justified_block_root = state.current_justified_root - - crosslinks = ( - state.current_crosslinks if spec.slot_to_epoch(slot) == spec.get_current_epoch(state) - else state.previous_crosslinks - ) - parent_crosslink = crosslinks[shard] - return spec.AttestationData( - beacon_block_root=block_root, - source_epoch=justified_epoch, - source_root=justified_block_root, - target_epoch=spec.slot_to_epoch(slot), - target_root=epoch_boundary_root, - crosslink=spec.Crosslink( - shard=shard, - start_epoch=parent_crosslink.end_epoch, - end_epoch=min(spec.slot_to_epoch(slot), parent_crosslink.end_epoch + spec.MAX_EPOCHS_PER_CROSSLINK), - data_root=spec.ZERO_HASH, - parent_root=spec.hash_tree_root(parent_crosslink), - ), - ) - - -def build_voluntary_exit(state, epoch, validator_index, privkey): - voluntary_exit = spec.VoluntaryExit( - epoch=epoch, - validator_index=validator_index, - ) - voluntary_exit.signature = bls.sign( - message_hash=signing_root(voluntary_exit), - privkey=privkey, - domain=spec.get_domain( - state=state, - domain_type=spec.DOMAIN_VOLUNTARY_EXIT, - message_epoch=epoch, - ) - ) - - return voluntary_exit - - -def build_deposit(state, - deposit_data_leaves, - pubkey, - privkey, - amount): - deposit_data = build_deposit_data(state, pubkey, privkey, amount) - - item = deposit_data.hash_tree_root() - index = len(deposit_data_leaves) - deposit_data_leaves.append(item) - tree = calc_merkle_tree_from_leaves(tuple(deposit_data_leaves)) - root = get_merkle_root((tuple(deposit_data_leaves))) - proof = list(get_merkle_proof(tree, item_index=index)) - assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) - - deposit = spec.Deposit( - proof=list(proof), - index=index, - data=deposit_data, - ) - - return deposit, root, deposit_data_leaves - - -def get_valid_proposer_slashing(state): - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] - privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey] - slot = state.slot - - header_1 = spec.BeaconBlockHeader( - slot=slot, - parent_root=spec.ZERO_HASH, - state_root=spec.ZERO_HASH, - body_root=spec.ZERO_HASH, - ) - header_2 = deepcopy(header_1) - header_2.parent_root = b'\x02' * 32 - header_2.slot = slot + 1 - - domain = spec.get_domain( - state=state, - domain_type=spec.DOMAIN_BEACON_PROPOSER, - ) - header_1.signature = bls.sign( - message_hash=signing_root(header_1), - privkey=privkey, - domain=domain, - ) - header_2.signature = bls.sign( - message_hash=signing_root(header_2), - privkey=privkey, - domain=domain, - ) - - return spec.ProposerSlashing( - proposer_index=validator_index, - header_1=header_1, - header_2=header_2, - ) - - -def get_valid_attester_slashing(state): - attestation_1 = get_valid_attestation(state) - attestation_2 = deepcopy(attestation_1) - attestation_2.data.target_root = b'\x01' * 32 - - return spec.AttesterSlashing( - attestation_1=spec.convert_to_indexed(state, attestation_1), - attestation_2=spec.convert_to_indexed(state, attestation_2), - ) - - -def get_valid_attestation(state, slot=None): - if slot is None: - slot = state.slot - - if spec.slot_to_epoch(slot) == spec.get_current_epoch(state): - shard = (state.latest_start_shard + slot) % spec.SLOTS_PER_EPOCH - else: - previous_shard_delta = spec.get_shard_delta(state, spec.get_previous_epoch(state)) - shard = (state.latest_start_shard - previous_shard_delta + slot) % spec.SHARD_COUNT - - attestation_data = build_attestation_data(state, slot, shard) - - crosslink_committee = spec.get_crosslink_committee( - state, - attestation_data.target_epoch, - attestation_data.crosslink.shard, - ) - - committee_size = len(crosslink_committee) - bitfield_length = (committee_size + 7) // 8 - aggregation_bitfield = b'\xC0' + b'\x00' * (bitfield_length - 1) - custody_bitfield = b'\x00' * bitfield_length - attestation = spec.Attestation( - aggregation_bitfield=aggregation_bitfield, - data=attestation_data, - custody_bitfield=custody_bitfield, - ) - participants = spec.get_attesting_indices( - state, - attestation.data, - attestation.aggregation_bitfield, - ) - assert len(participants) == 2 - - signatures = [] - for validator_index in participants: - privkey = privkeys[validator_index] - signatures.append( - get_attestation_signature( - state, - attestation.data, - privkey - ) - ) - - attestation.aggregation_signature = bls.aggregate_signatures(signatures) - return attestation - - -def get_valid_transfer(state, slot=None, sender_index=None, amount=None, fee=None): - if slot is None: - slot = state.slot - current_epoch = spec.get_current_epoch(state) - if sender_index is None: - sender_index = spec.get_active_validator_indices(state, current_epoch)[-1] - recipient_index = spec.get_active_validator_indices(state, current_epoch)[0] - transfer_pubkey = pubkeys[-1] - transfer_privkey = privkeys[-1] - - if fee is None: - fee = get_balance(state, sender_index) // 32 - if amount is None: - amount = get_balance(state, sender_index) - fee - - transfer = spec.Transfer( - sender=sender_index, - recipient=recipient_index, - amount=amount, - fee=fee, - slot=slot, - pubkey=transfer_pubkey, - signature=spec.ZERO_HASH, - ) - transfer.signature = bls.sign( - message_hash=signing_root(transfer), - privkey=transfer_privkey, - domain=spec.get_domain( - state=state, - domain_type=spec.DOMAIN_TRANSFER, - message_epoch=spec.get_current_epoch(state), - ) - ) - - # ensure withdrawal_credentials reproducable - state.validator_registry[transfer.sender].withdrawal_credentials = ( - spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(transfer.pubkey)[1:] - ) - - return transfer - - -def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0): - message_hash = spec.AttestationDataAndCustodyBit( - data=attestation_data, - custody_bit=custody_bit, - ).hash_tree_root() - - return bls.sign( - message_hash=message_hash, - privkey=privkey, - domain=spec.get_domain( - state=state, - domain_type=spec.DOMAIN_ATTESTATION, - message_epoch=attestation_data.target_epoch, - ) - ) - - -def fill_aggregate_attestation(state, attestation): - crosslink_committee = spec.get_crosslink_committee( - state, - attestation.data.target_epoch, - attestation.data.crosslink.shard, - ) - for i in range(len(crosslink_committee)): - attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) - - -def add_attestation_to_state(state, attestation, slot): - block = build_empty_block_for_next_slot(state) - block.slot = slot - block.body.attestations.append(attestation) - spec.state_transition(state, block) - - -def next_slot(state): - """ - Transition to the next slot via an empty block. - Return the empty block that triggered the transition. - """ - block = build_empty_block_for_next_slot(state) - spec.state_transition(state, block) - return block - - -def next_epoch(state): - """ - Transition to the start slot of the next epoch via an empty block. - Return the empty block that triggered the transition. - """ - block = build_empty_block_for_next_slot(state) - block.slot += spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) - spec.state_transition(state, block) - return block - - -def get_state_root(state, slot) -> bytes: - """ - Return the state root at a recent ``slot``. - """ - assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT - return state.latest_state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT] diff --git a/test_libs/pyspec/tests/phase0/test_finality.py b/test_libs/pyspec/tests/phase0/test_finality.py deleted file mode 100644 index 4ce7a0be4..000000000 --- a/test_libs/pyspec/tests/phase0/test_finality.py +++ /dev/null @@ -1,234 +0,0 @@ -from copy import deepcopy - -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py -import pytest - -# mark entire file as 'state' -pytestmark = pytest.mark.state -======= -import eth2spec.phase0.spec as spec -from eth2spec.phase0.spec import ( - get_current_epoch, - get_epoch_start_slot, -) -from .context import spec_state_test, never_bls -from .helpers.state import next_epoch -from .helpers.block import build_empty_block_for_next_slot, apply_empty_block -from .helpers.attestations import get_valid_attestation ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - - -def check_finality(state, - prev_state, - current_justified_changed, - previous_justified_changed, - finalized_changed): - if current_justified_changed: - assert state.current_justified_epoch > prev_state.current_justified_epoch - assert state.current_justified_root != prev_state.current_justified_root - else: - assert state.current_justified_epoch == prev_state.current_justified_epoch - assert state.current_justified_root == prev_state.current_justified_root - - if previous_justified_changed: - assert state.previous_justified_epoch > prev_state.previous_justified_epoch - assert state.previous_justified_root != prev_state.previous_justified_root - else: - assert state.previous_justified_epoch == prev_state.previous_justified_epoch - assert state.previous_justified_root == prev_state.previous_justified_root - - if finalized_changed: - assert state.finalized_epoch > prev_state.finalized_epoch - assert state.finalized_root != prev_state.finalized_root - else: - assert state.finalized_epoch == prev_state.finalized_epoch - assert state.finalized_root == prev_state.finalized_root - - -def next_epoch_with_attestations(state, - fill_cur_epoch, - fill_prev_epoch): - post_state = deepcopy(state) - blocks = [] - for _ in range(spec.SLOTS_PER_EPOCH): - block = helpers.build_empty_block_for_next_slot(post_state) - if fill_cur_epoch: - slot_to_attest = post_state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY + 1 -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py - if slot_to_attest >= spec.get_epoch_start_slot(spec.get_current_epoch(post_state)): - cur_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) - helpers.fill_aggregate_attestation(post_state, cur_attestation) -======= - if slot_to_attest >= get_epoch_start_slot(get_current_epoch(post_state)): - cur_attestation = get_valid_attestation(post_state, slot_to_attest) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - block.body.attestations.append(cur_attestation) - - if fill_prev_epoch: - slot_to_attest = post_state.slot - spec.SLOTS_PER_EPOCH + 1 -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py - prev_attestation = helpers.get_valid_attestation(post_state, slot_to_attest) - helpers.fill_aggregate_attestation(post_state, prev_attestation) -======= - prev_attestation = get_valid_attestation(post_state, slot_to_attest) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - block.body.attestations.append(prev_attestation) - - spec.state_transition(post_state, block) - blocks.append(block) - - return state, blocks, post_state - - -@never_bls -@spec_state_test -def test_finality_rule_4(state): - yield 'pre', state - - blocks = [] - for epoch in range(4): - prev_state, new_blocks, state = next_epoch_with_attestations(state, True, False) - blocks += new_blocks - - # justification/finalization skipped at GENESIS_EPOCH - if epoch == 0: - check_finality(state, prev_state, False, False, False) - # justification/finalization skipped at GENESIS_EPOCH + 1 - elif epoch == 1: - check_finality(state, prev_state, False, False, False) - elif epoch == 2: - check_finality(state, prev_state, True, False, False) - elif epoch >= 3: - # rule 4 of finality - check_finality(state, prev_state, True, True, True) - assert state.finalized_epoch == prev_state.current_justified_epoch - assert state.finalized_root == prev_state.current_justified_root - - yield 'blocks', blocks, [spec.BeaconBlock] - yield 'post', state - - -@never_bls -@spec_state_test -def test_finality_rule_1(state): - # get past first two epochs that finality does not run on -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py - helpers.next_epoch(state) - helpers.next_epoch(state) -======= - next_epoch(state) - apply_empty_block(state) - next_epoch(state) - apply_empty_block(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - - yield 'pre', state - - blocks = [] - for epoch in range(3): - prev_state, new_blocks, state = next_epoch_with_attestations(state, False, True) - blocks += new_blocks - - if epoch == 0: - check_finality(state, prev_state, True, False, False) - elif epoch == 1: - check_finality(state, prev_state, True, True, False) - elif epoch == 2: - # finalized by rule 1 - check_finality(state, prev_state, True, True, True) - assert state.finalized_epoch == prev_state.previous_justified_epoch - assert state.finalized_root == prev_state.previous_justified_root - - yield 'blocks', blocks, [spec.BeaconBlock] - yield 'post', state - - -@never_bls -@spec_state_test -def test_finality_rule_2(state): - # get past first two epochs that finality does not run on -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py - helpers.next_epoch(state) - helpers.next_epoch(state) -======= - next_epoch(state) - apply_empty_block(state) - next_epoch(state) - apply_empty_block(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - - yield 'pre', state - - blocks = [] - for epoch in range(3): - if epoch == 0: - prev_state, new_blocks, state = next_epoch_with_attestations(state, True, False) - check_finality(state, prev_state, True, False, False) - elif epoch == 1: - prev_state, new_blocks, state = next_epoch_with_attestations(state, False, False) - check_finality(state, prev_state, False, True, False) - elif epoch == 2: - prev_state, new_blocks, state = next_epoch_with_attestations(state, False, True) - # finalized by rule 2 - check_finality(state, prev_state, True, False, True) - assert state.finalized_epoch == prev_state.previous_justified_epoch - assert state.finalized_root == prev_state.previous_justified_root - - blocks += new_blocks - - yield 'blocks', blocks, [spec.BeaconBlock] - yield 'post', state - - -@never_bls -@spec_state_test -def test_finality_rule_3(state): - """ - Test scenario described here - https://github.com/ethereum/eth2.0-specs/issues/611#issuecomment-463612892 - """ - # get past first two epochs that finality does not run on -<<<<<<< HEAD:test_libs/pyspec/tests/phase0/test_finality.py - helpers.next_epoch(state) - helpers.next_epoch(state) -======= - next_epoch(state) - apply_empty_block(state) - next_epoch(state) - apply_empty_block(state) ->>>>>>> dev:test_libs/pyspec/eth2spec/test/test_finality.py - - yield 'pre', state - - blocks = [] - prev_state, new_blocks, state = next_epoch_with_attestations(state, True, False) - blocks += new_blocks - check_finality(state, prev_state, True, False, False) - - # In epoch N, JE is set to N, prev JE is set to N-1 - prev_state, new_blocks, state = next_epoch_with_attestations(state, True, False) - blocks += new_blocks - check_finality(state, prev_state, True, True, True) - - # In epoch N+1, JE is N, prev JE is N-1, and not enough messages get in to do anything - prev_state, new_blocks, state = next_epoch_with_attestations(state, False, False) - blocks += new_blocks - check_finality(state, prev_state, False, True, False) - - # In epoch N+2, JE is N, prev JE is N, and enough messages from the previous epoch get in to justify N+1. - # N+1 now becomes the JE. Not enough messages from epoch N+2 itself get in to justify N+2 - prev_state, new_blocks, state = next_epoch_with_attestations(state, False, True) - blocks += new_blocks - # rule 2 - check_finality(state, prev_state, True, False, True) - - # In epoch N+3, LJE is N+1, prev LJE is N, and enough messages get in to justify epochs N+2 and N+3. - prev_state, new_blocks, state = next_epoch_with_attestations(state, True, True) - blocks += new_blocks - # rule 3 - check_finality(state, prev_state, True, True, True) - assert state.finalized_epoch == prev_state.current_justified_epoch - assert state.finalized_root == prev_state.current_justified_root - - yield 'blocks', blocks, [spec.BeaconBlock] - yield 'post', state diff --git a/test_libs/pyspec/tests/phase0/test_sanity.py b/test_libs/pyspec/tests/phase0/test_sanity.py deleted file mode 100644 index 47e4917ab..000000000 --- a/test_libs/pyspec/tests/phase0/test_sanity.py +++ /dev/null @@ -1,402 +0,0 @@ -from copy import deepcopy - -import pytest - -from py_ecc import bls - -from eth2spec.utils.minimal_ssz import signing_root - -from eth2spec.utils.merkle_minimal import ( - calc_merkle_tree_from_leaves, - get_merkle_proof, - get_merkle_root, -) - - -# mark entire file as 'sanity' -pytestmark = pytest.mark.sanity - - -def test_slot_transition(state): - test_state = deepcopy(state) - spec.process_slot(test_state) - helpers.advance_slot(test_state) - assert test_state.slot == state.slot + 1 - assert helpers.get_state_root(test_state, state.slot) == state.hash_tree_root() - return test_state - - -def test_empty_block_transition(state): - test_state = deepcopy(state) - - block = helpers.build_empty_block_for_next_slot(test_state) - spec.state_transition(test_state, block) - - assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1 - assert spec.get_block_root_at_slot(test_state, state.slot) == block.parent_root - - return state, [block], test_state - - -def test_skipped_slots(state): - test_state = deepcopy(state) - block = helpers.build_empty_block_for_next_slot(test_state) - block.slot += 3 - - spec.state_transition(test_state, block) - - assert test_state.slot == block.slot - for slot in range(state.slot, test_state.slot): - assert spec.get_block_root_at_slot(test_state, slot) == block.parent_root - - return state, [block], test_state - - -def test_empty_epoch_transition(state): - test_state = deepcopy(state) - block = helpers.build_empty_block_for_next_slot(test_state) - block.slot += spec.SLOTS_PER_EPOCH - - spec.state_transition(test_state, block) - - assert test_state.slot == block.slot - for slot in range(state.slot, test_state.slot): - assert spec.get_block_root_at_slot(test_state, slot) == block.parent_root - - return state, [block], test_state - - -def test_empty_epoch_transition_not_finalizing(state): - test_state = deepcopy(state) - block = helpers.build_empty_block_for_next_slot(test_state) - block.slot += spec.SLOTS_PER_EPOCH * 5 - - spec.state_transition(test_state, block) - - assert test_state.slot == block.slot - assert test_state.finalized_epoch < spec.get_current_epoch(test_state) - 4 - for index in range(len(test_state.validator_registry)): - assert helpers.get_balance(test_state, index) < helpers.get_balance(state, index) - - return state, [block], test_state - - -def test_proposer_slashing(state): - test_state = deepcopy(state) - proposer_slashing = helpers.get_valid_proposer_slashing(state) - validator_index = proposer_slashing.proposer_index - - # - # Add to state via block transition - # - block = helpers.build_empty_block_for_next_slot(test_state) - block.body.proposer_slashings.append(proposer_slashing) - spec.state_transition(test_state, block) - - assert not state.validator_registry[validator_index].slashed - - slashed_validator = test_state.validator_registry[validator_index] - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - assert helpers.get_balance(test_state, validator_index) < helpers.get_balance(state, validator_index) - - return state, [block], test_state - - -def test_attester_slashing(state): - test_state = deepcopy(state) - attester_slashing = helpers.get_valid_attester_slashing(state) - validator_index = attester_slashing.attestation_1.custody_bit_0_indices[0] - - # - # Add to state via block transition - # - block = helpers.build_empty_block_for_next_slot(test_state) - block.body.attester_slashings.append(attester_slashing) - spec.state_transition(test_state, block) - - assert not state.validator_registry[validator_index].slashed - - slashed_validator = test_state.validator_registry[validator_index] - assert slashed_validator.slashed - assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH - assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - assert helpers.get_balance(test_state, validator_index) < helpers.get_balance(state, validator_index) - - proposer_index = spec.get_beacon_proposer_index(test_state) - # gained whistleblower reward - assert ( - helpers.get_balance(test_state, proposer_index) > - helpers.get_balance(state, proposer_index) - ) - - return state, [block], test_state - - -def test_deposit_in_block(state): - pre_state = deepcopy(state) - test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - index = len(test_deposit_data_leaves) - pubkey = helpers.pubkeys[index] - privkey = helpers.privkeys[index] - deposit_data = helpers.build_deposit_data(pre_state, pubkey, privkey, spec.MAX_EFFECTIVE_BALANCE) - - item = deposit_data.hash_tree_root() - test_deposit_data_leaves.append(item) - tree = calc_merkle_tree_from_leaves(tuple(test_deposit_data_leaves)) - root = get_merkle_root((tuple(test_deposit_data_leaves))) - proof = list(get_merkle_proof(tree, item_index=index)) - assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, index, root) - - deposit = spec.Deposit( - proof=list(proof), - index=index, - data=deposit_data, - ) - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(test_deposit_data_leaves) - post_state = deepcopy(pre_state) - block = helpers.build_empty_block_for_next_slot(post_state) - block.body.deposits.append(deposit) - - spec.state_transition(post_state, block) - assert len(post_state.validator_registry) == len(state.validator_registry) + 1 - assert len(post_state.balances) == len(state.balances) + 1 - assert helpers.get_balance(post_state, index) == spec.MAX_EFFECTIVE_BALANCE - assert post_state.validator_registry[index].pubkey == helpers.pubkeys[index] - - return pre_state, [block], post_state - - -def test_deposit_top_up(state): - pre_state = deepcopy(state) - test_deposit_data_leaves = [spec.ZERO_HASH] * len(pre_state.validator_registry) - - validator_index = 0 - amount = spec.MAX_EFFECTIVE_BALANCE // 4 - pubkey = helpers.pubkeys[validator_index] - privkey = helpers.privkeys[validator_index] - deposit_data = helpers.build_deposit_data(pre_state, pubkey, privkey, amount) - - merkle_index = len(test_deposit_data_leaves) - item = deposit_data.hash_tree_root() - test_deposit_data_leaves.append(item) - tree = calc_merkle_tree_from_leaves(tuple(test_deposit_data_leaves)) - root = get_merkle_root((tuple(test_deposit_data_leaves))) - proof = list(get_merkle_proof(tree, item_index=merkle_index)) - assert spec.verify_merkle_branch(item, proof, spec.DEPOSIT_CONTRACT_TREE_DEPTH, merkle_index, root) - - deposit = spec.Deposit( - proof=list(proof), - index=merkle_index, - data=deposit_data, - ) - - pre_state.latest_eth1_data.deposit_root = root - pre_state.latest_eth1_data.deposit_count = len(test_deposit_data_leaves) - block = helpers.build_empty_block_for_next_slot(pre_state) - block.body.deposits.append(deposit) - - pre_balance = helpers.get_balance(pre_state, validator_index) - post_state = deepcopy(pre_state) - spec.state_transition(post_state, block) - assert len(post_state.validator_registry) == len(pre_state.validator_registry) - assert len(post_state.balances) == len(pre_state.balances) - assert helpers.get_balance(post_state, validator_index) == pre_balance + amount - - return pre_state, [block], post_state - - -def test_attestation(state): - state.slot = spec.SLOTS_PER_EPOCH - test_state = deepcopy(state) - attestation = helpers.get_valid_attestation(state) - - # - # Add to state via block transition - # - attestation_block = helpers.build_empty_block_for_next_slot(test_state) - attestation_block.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - attestation_block.body.attestations.append(attestation) - spec.state_transition(test_state, attestation_block) - - assert len(test_state.current_epoch_attestations) == len(state.current_epoch_attestations) + 1 - - # - # Epoch transition should move to previous_epoch_attestations - # - pre_current_epoch_attestations = deepcopy(test_state.current_epoch_attestations) - - epoch_block = helpers.build_empty_block_for_next_slot(test_state) - epoch_block.slot += spec.SLOTS_PER_EPOCH - spec.state_transition(test_state, epoch_block) - - assert len(test_state.current_epoch_attestations) == 0 - assert test_state.previous_epoch_attestations == pre_current_epoch_attestations - - return state, [attestation_block, epoch_block], test_state - - -def test_voluntary_exit(state): - pre_state = deepcopy(state) - validator_index = spec.get_active_validator_indices( - pre_state, - spec.get_current_epoch(pre_state) - )[-1] - - # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit - pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH - - post_state = deepcopy(pre_state) - - voluntary_exit = spec.VoluntaryExit( - epoch=spec.get_current_epoch(pre_state), - validator_index=validator_index, - ) - voluntary_exit.signature = bls.sign( - message_hash=signing_root(voluntary_exit), - privkey=helpers.privkeys[validator_index], - domain=spec.get_domain( - state=pre_state, - domain_type=spec.DOMAIN_VOLUNTARY_EXIT, - ) - ) - - # - # Add to state via block transition - # - initiate_exit_block = helpers.build_empty_block_for_next_slot(post_state) - initiate_exit_block.body.voluntary_exits.append(voluntary_exit) - spec.state_transition(post_state, initiate_exit_block) - - assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH - - # - # Process within epoch transition - # - exit_block = helpers.build_empty_block_for_next_slot(post_state) - exit_block.slot += spec.SLOTS_PER_EPOCH - spec.state_transition(post_state, exit_block) - - assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH - - return pre_state, [initiate_exit_block, exit_block], post_state - - -def test_transfer(state): - # overwrite default 0 to test - spec.apply_constants_preset({"MAX_TRANSFERS": 1}) - - pre_state = deepcopy(state) - current_epoch = spec.get_current_epoch(pre_state) - sender_index = spec.get_active_validator_indices(pre_state, current_epoch)[-1] - recipient_index = spec.get_active_validator_indices(pre_state, current_epoch)[0] - transfer_pubkey = helpers.pubkeys[-1] - transfer_privkey = helpers.privkeys[-1] - amount = helpers.get_balance(pre_state, sender_index) - pre_transfer_recipient_balance = helpers.get_balance(pre_state, recipient_index) - transfer = spec.Transfer( - sender=sender_index, - recipient=recipient_index, - amount=amount, - fee=0, - slot=pre_state.slot + 1, - pubkey=transfer_pubkey, - ) - transfer.signature = bls.sign( - message_hash=signing_root(transfer), - privkey=transfer_privkey, - domain=spec.get_domain( - state=pre_state, - domain_type=spec.DOMAIN_TRANSFER, - ) - ) - - # ensure withdrawal_credentials reproducable - pre_state.validator_registry[sender_index].withdrawal_credentials = ( - spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(transfer_pubkey)[1:] - ) - # un-activate so validator can transfer - pre_state.validator_registry[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH - - post_state = deepcopy(pre_state) - # - # Add to state via block transition - # - block = helpers.build_empty_block_for_next_slot(post_state) - block.body.transfers.append(transfer) - spec.state_transition(post_state, block) - - sender_balance = helpers.get_balance(post_state, sender_index) - recipient_balance = helpers.get_balance(post_state, recipient_index) - assert sender_balance == 0 - assert recipient_balance == pre_transfer_recipient_balance + amount - - return pre_state, [block], post_state - - -def test_balance_driven_status_transitions(state): - current_epoch = spec.get_current_epoch(state) - validator_index = spec.get_active_validator_indices(state, current_epoch)[-1] - - assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH - - # set validator balance to below ejection threshold - state.validator_registry[validator_index].effective_balance = spec.EJECTION_BALANCE - - post_state = deepcopy(state) - # - # trigger epoch transition - # - block = helpers.build_empty_block_for_next_slot(post_state) - block.slot += spec.SLOTS_PER_EPOCH - spec.state_transition(post_state, block) - - assert post_state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH - - return state, [block], post_state - - -def test_historical_batch(state): - state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1 - - post_state = deepcopy(state) - - block = helpers.build_empty_block_for_next_slot(post_state) - - spec.state_transition(post_state, block) - - assert post_state.slot == block.slot - assert spec.get_current_epoch(post_state) % (spec.SLOTS_PER_HISTORICAL_ROOT // spec.SLOTS_PER_EPOCH) == 0 - assert len(post_state.historical_roots) == len(state.historical_roots) + 1 - - return state, [block], post_state - - -def test_eth1_data_votes(state): - post_state = deepcopy(state) - - expected_votes = 0 - assert len(state.eth1_data_votes) == expected_votes - - blocks = [] - for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): - block = helpers.build_empty_block_for_next_slot(post_state) - spec.state_transition(post_state, block) - expected_votes += 1 - assert len(post_state.eth1_data_votes) == expected_votes - blocks.append(block) - - block = helpers.build_empty_block_for_next_slot(post_state) - spec.state_transition(post_state, block) - blocks.append(block) - - assert post_state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 - assert len(post_state.eth1_data_votes) == 1 - - return state, blocks, post_state diff --git a/test_libs/pyspec/tests/phase1/__init__.py b/test_libs/pyspec/tests/phase1/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py b/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py deleted file mode 100644 index 246ba163c..000000000 --- a/test_libs/pyspec/tests/phase1/block_processing_phase1/test_phase0_block_processing.py +++ /dev/null @@ -1,7 +0,0 @@ -from tests.phase0.block_processing.test_process_attestation import * -from tests.phase0.block_processing.test_process_attester_slashing import * -from tests.phase0.block_processing.test_process_block_header import * -from tests.phase0.block_processing.test_process_deposit import * -from tests.phase0.block_processing.test_process_proposer_slashing import * -from tests.phase0.block_processing.test_process_transfer import * -from tests.phase0.block_processing.test_voluntary_exit import * diff --git a/test_libs/pyspec/tests/phase1/conftest.py b/test_libs/pyspec/tests/phase1/conftest.py deleted file mode 100644 index 4226241d7..000000000 --- a/test_libs/pyspec/tests/phase1/conftest.py +++ /dev/null @@ -1,39 +0,0 @@ -import pytest - -from eth2spec.phase1 import spec -from preset_loader import loader - -from tests.phase0 import helpers as phase1_helpers -from tests.phase1 import helpers as helpers - - -def pytest_addoption(parser): - parser.addoption( - "--config", action="store", default="minimal", help="config: make the pyspec use the specified configuration" - ) - - -@pytest.fixture(autouse=True) -def config(request): - config_name = request.config.getoption("--config") - presets = loader.load_presets('../../configs/', config_name) - spec.apply_constants_preset(presets) - helpers.spec = spec - phase1_helpers.spec = spec - request.function.__globals__['spec'] = spec - request.function.__globals__['helpers'] = helpers - - -@pytest.fixture -def num_validators(config): - return spec.SLOTS_PER_EPOCH * 8 - - -@pytest.fixture -def deposit_data_leaves(): - return list() - - -@pytest.fixture -def state(num_validators, deposit_data_leaves): - return helpers.create_genesis_state(num_validators, deposit_data_leaves) diff --git a/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py b/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py deleted file mode 100644 index ec3012560..000000000 --- a/test_libs/pyspec/tests/phase1/epoch_processing/test_phase0_epoch_processing.py +++ /dev/null @@ -1,2 +0,0 @@ -from tests.phase0.epoch_processing.test_process_crosslinks import * -from tests.phase0.epoch_processing.test_process_registry_updates import * diff --git a/test_libs/pyspec/tests/phase1/helpers.py b/test_libs/pyspec/tests/phase1/helpers.py deleted file mode 100644 index d7adbd802..000000000 --- a/test_libs/pyspec/tests/phase1/helpers.py +++ /dev/null @@ -1,39 +0,0 @@ -from py_ecc import bls - -from tests.phase0.helpers import * - - -def get_valid_early_derived_secret_reveal(state, epoch=None): - current_epoch = spec.get_current_epoch(state) - revealed_index = spec.get_active_validator_indices(state, current_epoch)[-1] - masker_index = spec.get_active_validator_indices(state, current_epoch)[0] - - if epoch is None: - epoch = current_epoch + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING - - reveal = bls.sign( - message_hash=spec.hash_tree_root(epoch), - privkey=privkeys[revealed_index], - domain=spec.get_domain( - state=state, - domain_type=spec.DOMAIN_RANDAO, - message_epoch=epoch, - ), - ) - mask = bls.sign( - message_hash=spec.hash_tree_root(epoch), - privkey=privkeys[masker_index], - domain=spec.get_domain( - state=state, - domain_type=spec.DOMAIN_RANDAO, - message_epoch=epoch, - ), - ) - - return spec.EarlyDerivedSecretReveal( - revealed_index=revealed_index, - epoch=epoch, - reveal=reveal, - masker_index=masker_index, - mask=mask, - ) diff --git a/test_libs/pyspec/tests/phase1/test_finality.py b/test_libs/pyspec/tests/phase1/test_finality.py deleted file mode 100644 index 1e4e0374a..000000000 --- a/test_libs/pyspec/tests/phase1/test_finality.py +++ /dev/null @@ -1,4 +0,0 @@ -import pytest - - -from tests.phase0.test_finality import * diff --git a/test_libs/pyspec/tests/phase1/test_sanity.py b/test_libs/pyspec/tests/phase1/test_sanity.py deleted file mode 100644 index a9b4d7190..000000000 --- a/test_libs/pyspec/tests/phase1/test_sanity.py +++ /dev/null @@ -1,4 +0,0 @@ -import pytest - - -from tests.phase0.test_sanity import * From 92916e5383ee2eb7139e52bed283bf979feb160d Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 13:08:42 +0200 Subject: [PATCH 39/55] Tests run with both spec versions --- test_libs/pyspec/eth2spec/test/context.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index d0869ba68..670654a92 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -110,4 +110,13 @@ def with_phase1(fn): return entry -with_all_phases = with_phase0 +def with_all_phases(fn): + """ + Decorator to run everything with all availible spec phases + """ + def entry(*args, **kw): + kw['spec'] = spec_phase0 + fn(*args, **kw) + kw['spec'] = spec_phase1 + return fn(*args, **kw) + return entry From 28d98b5cf47ce2b85a618917a5a02b36b603ba93 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Fri, 31 May 2019 13:20:10 +0200 Subject: [PATCH 40/55] PEP8 cleanups --- Makefile | 3 +-- .../test_process_early_derived_secret_reveal.py | 5 +++-- test_libs/pyspec/eth2spec/test/helpers/deposits.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index af71f44fb..33eb3ecec 100644 --- a/Makefile +++ b/Makefile @@ -50,8 +50,7 @@ install_lint: lint: $(PY_SPEC_ALL_TARGETS) cd $(PY_SPEC_DIR); . venv/bin/activate; \ - flake8 --max-line-length=120 ./eth2spec; \ - flake8 --max-line-length=120 --ignore=F401,F403,F405,F821 ./tests; + flake8 --max-line-length=120 ./eth2spec # "make pyspec" to create the pyspec for all phases. pyspec: $(PY_SPEC_ALL_TARGETS) diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py index 4b4608d4d..4b7de56c8 100644 --- a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py @@ -55,7 +55,7 @@ def test_reveal_from_current_epoch(spec, state): # @spec_state_test # def test_reveal_from_past_epoch(state): # randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state) - 1) -# +# # yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) @@ -99,7 +99,8 @@ def test_double_reveal(spec, state): intermediate_state, spec.get_current_epoch(pre_state) + spec.RANDAO_PENALTY_EPOCHS + 1, ) - post_state = dict(run_early_derived_secret_reveal_processing(spec, intermediate_state, randao_key_reveal2, False))['post'] + res = dict(run_early_derived_secret_reveal_processing(spec, intermediate_state, randao_key_reveal2, False)) + post_state = res['post'] yield 'randao_key_reveal', [randao_key_reveal1, randao_key_reveal2] yield 'post', post_state diff --git a/test_libs/pyspec/eth2spec/test/helpers/deposits.py b/test_libs/pyspec/eth2spec/test/helpers/deposits.py index 9711f8b0f..6d9b6e118 100644 --- a/test_libs/pyspec/eth2spec/test/helpers/deposits.py +++ b/test_libs/pyspec/eth2spec/test/helpers/deposits.py @@ -70,7 +70,7 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash(pubkey)[1:] deposit, root, deposit_data_leaves = build_deposit( - spec, + spec, state, deposit_data_leaves, pubkey, From 226adb35dfe63246509beb71baf6c2f9eb90465c Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 3 Jun 2019 14:22:03 +0200 Subject: [PATCH 41/55] Adds Docstrings and type-checking to spec builder. --- scripts/build_spec.py | 58 ++++++++++++++++++++++++++++---------- scripts/function_puller.py | 24 ++++++++++++---- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/scripts/build_spec.py b/scripts/build_spec.py index e4ad9dc5f..2266af4ef 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -1,6 +1,13 @@ import re -import function_puller +from function_puller import ( + get_spec, + SpecObject, +) from argparse import ArgumentParser +from typing import ( + Dict, + Optional, +) PHASE0_IMPORTS = '''from typing import ( @@ -107,8 +114,16 @@ def apply_constants_preset(preset: Dict[str, Any]): ''' -def objects_to_spec(functions, constants, ssz_objects, inserts, imports): - new_type_definitions = '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) +def objects_to_spec(functions: Dict[str, str], + constants: Dict[str, str], + ssz_objects: Dict[str, str], + inserts: Dict[str, str], + imports: Dict[str, str]) -> str: + """ + Given all the objects that constitute a spec, combine them into a single pyfile. + """ + new_type_definitions = \ + '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants)) ssz_objects_instantiation_spec = '\n'.join(map( @@ -120,7 +135,7 @@ def objects_to_spec(functions, constants, ssz_objects, inserts, imports): ssz_objects )) ssz_objects_reinitialization_spec = ( - 'def init_SSZ_types():\n global_vars = globals()\n' + 'def init_SSZ_types():\n global_vars = globals()\n' + ssz_objects_reinitialization_spec ) spec = ( @@ -139,19 +154,22 @@ def objects_to_spec(functions, constants, ssz_objects, inserts, imports): return spec -def combine_functions(old_funcitons, new_functions): +def combine_functions(old_funcitons: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]: for key, value in new_functions.items(): old_funcitons[key] = value return old_funcitons -def combine_constants(old_constants, new_constants): +def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]: for key, value in new_constants.items(): old_constants[key] = value return old_constants -def dependency_order_ssz_objects(objects): +def dependency_order_ssz_objects(objects: Dict[str, str]) -> Dict[str, str]: + """ + Determines which SSZ Object is depenedent on which other and orders them appropriately + """ items = list(objects.items()) for key, value in items: dependencies = re.findall(r'(: [\[]*[A-Z][a-z][\w]+)', value) @@ -164,7 +182,11 @@ def dependency_order_ssz_objects(objects): objects[item] = objects.pop(item) -def combine_ssz_objects(old_objects, new_objects): +def combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]: + """ + Thakes in old spec and new spec ssz objects, combines them, + and returns the newer versions of the objects in dependency order. + """ for key, value in new_objects.items(): # remove leading "{" and trailing "\n}" old_objects[key] = old_objects.get(key, '')[1:-3] @@ -179,7 +201,10 @@ def combine_ssz_objects(old_objects, new_objects): combine_inserts = combine_functions -def combine_spec_objects(spec0, spec1): +def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject: + """ + Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function. + """ functions0, constants0, ssz_objects0, inserts0 = spec0 functions1, constants1, ssz_objects1, inserts1 = spec1 functions = combine_functions(functions0, functions1) @@ -189,8 +214,8 @@ def combine_spec_objects(spec0, spec1): return functions, constants, ssz_objects, inserts -def build_phase0_spec(sourcefile, outfile=None): - functions, constants, ssz_objects, inserts = function_puller.get_spec(sourcefile) +def build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]: + functions, constants, ssz_objects, inserts = get_spec(sourcefile) spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS) if outfile is not None: with open(outfile, 'w') as out: @@ -199,10 +224,13 @@ def build_phase0_spec(sourcefile, outfile=None): return spec -def build_phase1_spec(phase0_sourcefile, phase1_custody_sourcefile, phase1_shard_sourcefile, outfile=None): - phase0_spec = function_puller.get_spec(phase0_sourcefile) - phase1_custody = function_puller.get_spec(phase1_custody_sourcefile) - phase1_shard_data = function_puller.get_spec(phase1_shard_sourcefile) +def build_phase1_spec(phase0_sourcefile: str, + phase1_custody_sourcefile: str, + phase1_shard_sourcefile: str, + outfile: str=None) -> Optional[str]: + phase0_spec = get_spec(phase0_sourcefile) + phase1_custody = get_spec(phase1_custody_sourcefile) + phase1_shard_data = get_spec(phase1_shard_sourcefile) spec_objects = phase0_spec for value in [phase1_custody, phase1_shard_data]: spec_objects = combine_spec_objects(spec_objects, value) diff --git a/scripts/function_puller.py b/scripts/function_puller.py index 72cb0365c..7a10140cd 100644 --- a/scripts/function_puller.py +++ b/scripts/function_puller.py @@ -1,13 +1,25 @@ import re -from typing import Dict, Tuple +from typing import Dict, Tuple, NewType FUNCTION_REGEX = r'^def [\w_]*' BEGIN_INSERT_REGEX = r'# begin insert ' END_INSERT_REGEX = r'# end insert' +SpecObject = NewType('SpecObjects', Tuple[Dict[str, str], Dict[str, str], Dict[str, str], Dict[str, str]]) -def get_spec(file_name: str) -> Tuple[Dict[str, str], Dict[str, str], Dict[str, str], Dict[str, str]]: + +def get_spec(file_name: str) -> SpecObject: + """ + Takes in the file name of a spec.md file, opens it and returns the following objects: + functions = {function_name: function_code} + constants= {constant_name: constant_code} + ssz_objects= {object_name: object} + inserts= {insert_tag: code to be inserted} + + Note: This function makes heavy use of the inherent ordering of dicts, + if this is not supported by your python version, it will not work. + """ pulling_from = None # line number of start of latest object current_name = None # most recent section title insert_name = None # stores the label of the current insert object @@ -27,21 +39,23 @@ def get_spec(file_name: str) -> Tuple[Dict[str, str], Dict[str, str], Dict[str, elif line[:3] == '```': pulling_from = None elif inserts_matcher.match(line) is not None: + # Find @insert names insert_name = re.search(r'@[\w]*', line).group(0) elif insert_name is not None: + # In insert mode, either the next line is more code, or the end of the insert if re.match(END_INSERT_REGEX, line) is not None: insert_name = None else: inserts[insert_name] = inserts.get(insert_name, '') + line + '\n' else: - # Handle function definitions + # Handle function definitions & ssz_objects if pulling_from is not None: func_match = function_matcher.match(line) if func_match is not None: current_name = func_match.group(0) - if function_matcher.match(current_name) is None: + if function_matcher.match(current_name) is None: # The current line is an SSZ Object ssz_objects[current_name] = ssz_objects.get(current_name, '') + line + '\n' - else: + else: # The current line is code functions[current_name] = functions.get(current_name, '') + line + '\n' # Handle constant table entries elif pulling_from is None and len(line) > 0 and line[0] == '|': From 381fcc321510a675cc63370d0db331dccf3201e7 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Mon, 3 Jun 2019 15:14:20 +0200 Subject: [PATCH 42/55] Adds label explainer --- scripts/README.md | 32 ++++++++++++++++++++++++++++++++ scripts/build_spec.py | 8 ++++---- 2 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 scripts/README.md diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..d6ce4c1bd --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,32 @@ +# Building pyspecs from specs.md + +The benefits of the particular spec design is that a given `spec.md` file can be converted to a `spec.py` file for the purposes of testing and linting. The result of this is that bugs are discovered and patched more quickly. + +Specs can bue built from either a single markdown document or multiple files that must be combined in a given order. Given 2 spec objects, `build_spec.combine_spec_objects` will combine them into a single spec object which, subsequently, can be converted into a `specs.py`. + +## Usage + +For usage of the spec builder run `python3 -m build_spec --help`. + +## `@Labels` and inserts + +The functioning of the spec combiner is largely automatic in that given `spec0.md` and `spec1.md`, in that SSZ Objects will be extended and old functions will be overwritten. Extra functionality is provided for more granular control over how files are combined. In the event that only a small portion of code is to be added to an existing function, insert functionality is provided. This saves having to completely redefine the old function from `spec0.md` in `spec1.md`. This is done by marking where the change is to occur in the old file and marking which code is to be inserted in the new file. This is done as follows: + +* In the old file, a label is added as a python comment marking where the code is to be inserted. This would appear as follows in `spec0.md`: + +```python +def foo(x): + x << 1 + # @YourLabelHere + return x +``` + +* In spec1, the new code could then be inserted by having a code-block that looked as follows: + +```python +#begin insert @YourLabelHere + x += x +#end insert @YourLabelHere +``` + +**Note** that the code to be inserted has the **same level of indentation** as the surrounding code of its destination insert point. diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 2266af4ef..4ba9b616a 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -154,10 +154,10 @@ def objects_to_spec(functions: Dict[str, str], return spec -def combine_functions(old_funcitons: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]: +def combine_functions(old_functions: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]: for key, value in new_functions.items(): - old_funcitons[key] = value - return old_funcitons + old_functions[key] = value + return old_functions def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]: @@ -184,7 +184,7 @@ def dependency_order_ssz_objects(objects: Dict[str, str]) -> Dict[str, str]: def combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]: """ - Thakes in old spec and new spec ssz objects, combines them, + Takes in old spec and new spec ssz objects, combines them, and returns the newer versions of the objects in dependency order. """ for key, value in new_objects.items(): From c06a60c95a89359d02dbc0979c75d8a9c9db88ae Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Tue, 4 Jun 2019 15:37:08 +0200 Subject: [PATCH 43/55] Fix descriptions Co-Authored-By: Hsiao-Wei Wang --- scripts/README.md | 4 ++-- test_libs/pyspec/eth2spec/test/context.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/README.md b/scripts/README.md index d6ce4c1bd..b47c238ce 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,8 +1,8 @@ # Building pyspecs from specs.md -The benefits of the particular spec design is that a given `spec.md` file can be converted to a `spec.py` file for the purposes of testing and linting. The result of this is that bugs are discovered and patched more quickly. +The benefit of the particular spec design is that the given markdown files can be converted to a `spec.py` file for the purposes of testing and linting. The result of this is that bugs are discovered and patched more quickly. -Specs can bue built from either a single markdown document or multiple files that must be combined in a given order. Given 2 spec objects, `build_spec.combine_spec_objects` will combine them into a single spec object which, subsequently, can be converted into a `specs.py`. +Specs can be built from either a single markdown document or multiple files that must be combined in a given order. Given 2 spec objects, `build_spec.combine_spec_objects` will combine them into a single spec object which, subsequently, can be converted into a `specs.py`. ## Usage diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 670654a92..046a71caa 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -92,7 +92,7 @@ def bls_switch(fn): def with_phase0(fn): """ - Decorator to use phase 0's spec and helpers + Decorator to use phase 0's spec. """ def entry(*args, **kw): kw['spec'] = spec_phase0 @@ -102,7 +102,7 @@ def with_phase0(fn): def with_phase1(fn): """ - Decorator to use phase 1's spec and helpers + Decorator to use phase 1's spec """ def entry(*args, **kw): kw['spec'] = spec_phase1 From 9d00a76493a386b79d20f1aca8fcf1a0c39b4372 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Tue, 4 Jun 2019 16:14:14 +0200 Subject: [PATCH 44/55] Skips tests properly --- ...est_process_early_derived_secret_reveal.py | 16 ++-- .../eth2spec/test/sanity/test_blocks.py | 88 ++++++++++--------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py index 4b7de56c8..c28c2e859 100644 --- a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py @@ -1,3 +1,5 @@ +import pytest + from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal from eth2spec.test.context import with_phase1, spec_state_test, expect_assertion_error @@ -51,12 +53,14 @@ def test_reveal_from_current_epoch(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -# @with_phase1 -# @spec_state_test -# def test_reveal_from_past_epoch(state): -# randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state) - 1) -# -# yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) +@with_phase1 +@spec_state_test +def test_reveal_from_past_epoch(spec, state): + if spec.get_current_epoch(state) < 1: + pytest.skip('testing of previous epoch requires epoch of at least 1') + randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state) - 1) + + yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) @with_phase1 diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 054458632..63da6aa37 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -72,24 +72,25 @@ def test_empty_epoch_transition(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -# @spec_state_test -# def test_empty_epoch_transition_not_finalizing(spec, state): -# # copy for later balance lookups. -# pre_state = deepcopy(state) -# yield 'pre', state -# -# block = build_empty_block_for_next_slot(spec, state) -# block.slot += spec.SLOTS_PER_EPOCH * 5 -# sign_block(spec, state, block, proposer_index=0) -# yield 'blocks', [block], [spec.BeaconBlock] -# -# spec.state_transition(state, block) -# yield 'post', state -# -# assert state.slot == block.slot -# assert state.finalized_epoch < spec.get_current_epoch(state) - 4 -# for index in range(len(state.validator_registry)): -# assert get_balance(state, index) < get_balance(pre_state, index) +@with_all_phases +@spec_state_test +def test_empty_epoch_transition_not_finalizing(spec, state): + # copy for later balance lookups. + pre_state = deepcopy(state) + yield 'pre', state + + block = build_empty_block_for_next_slot(spec, state) + block.slot += spec.SLOTS_PER_EPOCH * 5 + sign_block(spec, state, block, proposer_index=0) + yield 'blocks', [block], [spec.BeaconBlock] + + spec.state_transition(state, block) + yield 'post', state + + assert state.slot == block.slot + assert state.finalized_epoch < spec.get_current_epoch(state) - 4 + for index in range(len(state.validator_registry)): + assert get_balance(state, index) < get_balance(pre_state, index) @with_all_phases @@ -378,28 +379,29 @@ def test_historical_batch(spec, state): assert len(state.historical_roots) == pre_historical_roots_len + 1 -# @spec_state_test -# def test_eth1_data_votes(spec, state): -# yield 'pre', state -# -# expected_votes = 0 -# assert len(state.eth1_data_votes) == expected_votes -# -# blocks = [] -# for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): -# block = build_empty_block_for_next_slot(spec, state) -# spec.state_transition(state, block) -# expected_votes += 1 -# assert len(state.eth1_data_votes) == expected_votes -# blocks.append(block) -# -# block = build_empty_block_for_next_slot(spec, state) -# blocks.append(block) -# -# spec.state_transition(state, block) -# -# yield 'blocks', [block], [spec.BeaconBlock] -# yield 'post', state -# -# assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 -# assert len(state.eth1_data_votes) == 1 +@with_all_phases +@spec_state_test +def test_eth1_data_votes(spec, state): + yield 'pre', state + + expected_votes = 0 + assert len(state.eth1_data_votes) == expected_votes + + blocks = [] + for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): + block = build_empty_block_for_next_slot(spec, state) + spec.state_transition(state, block) + expected_votes += 1 + assert len(state.eth1_data_votes) == expected_votes + blocks.append(block) + + block = build_empty_block_for_next_slot(spec, state) + blocks.append(block) + + spec.state_transition(state, block) + + yield 'blocks', [block], [spec.BeaconBlock] + yield 'post', state + + assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 + assert len(state.eth1_data_votes) == 1 From f6bb47c402b5ec9f9db3324e7387b243dcf7e834 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Tue, 4 Jun 2019 17:08:18 +0200 Subject: [PATCH 45/55] Apply @dankrad's suggestions from code review --- scripts/README.md | 2 +- scripts/build_spec.py | 2 +- test_libs/pyspec/eth2spec/utils/minimal_ssz.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/README.md b/scripts/README.md index b47c238ce..25b46decf 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -10,7 +10,7 @@ For usage of the spec builder run `python3 -m build_spec --help`. ## `@Labels` and inserts -The functioning of the spec combiner is largely automatic in that given `spec0.md` and `spec1.md`, in that SSZ Objects will be extended and old functions will be overwritten. Extra functionality is provided for more granular control over how files are combined. In the event that only a small portion of code is to be added to an existing function, insert functionality is provided. This saves having to completely redefine the old function from `spec0.md` in `spec1.md`. This is done by marking where the change is to occur in the old file and marking which code is to be inserted in the new file. This is done as follows: +The functioning of the spec combiner is largely automatic in that given `spec0.md` and `spec1.md`, SSZ Objects will be extended and old functions will be overwritten. Extra functionality is provided for more granular control over how files are combined. In the event that only a small portion of code is to be added to an existing function, insert functionality is provided. This saves having to completely redefine the old function from `spec0.md` in `spec1.md`. This is done by marking where the change is to occur in the old file and marking which code is to be inserted in the new file. This is done as follows: * In the old file, a label is added as a python comment marking where the code is to be inserted. This would appear as follows in `spec0.md`: diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 4ba9b616a..c6bb55292 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -166,7 +166,7 @@ def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, st return old_constants -def dependency_order_ssz_objects(objects: Dict[str, str]) -> Dict[str, str]: +def dependency_order_ssz_objects(objects: Dict[str, str]) -> None: """ Determines which SSZ Object is depenedent on which other and orders them appropriately """ diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py index f46c0acef..9a555af66 100644 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py @@ -56,8 +56,7 @@ class Vector(): return self.length -def type_of(obj): - return obj.__class__ +type_of = type def empty(obj): From e5fb91c4a2ba2eaa24db1840bf4e85a079918a23 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 5 Jun 2019 16:23:44 +0200 Subject: [PATCH 46/55] Make test generators work with phase 1 execution --- test_generators/epoch_processing/main.py | 6 +- test_generators/operations/main.py | 6 +- test_generators/sanity/main.py | 6 +- test_generators/shuffling/main.py | 9 ++- .../eth2spec/test/sanity/test_blocks.py | 72 +++++++++---------- 5 files changed, 54 insertions(+), 45 deletions(-) diff --git a/test_generators/epoch_processing/main.py b/test_generators/epoch_processing/main.py index 8f067e4a3..2ce895fc5 100644 --- a/test_generators/epoch_processing/main.py +++ b/test_generators/epoch_processing/main.py @@ -1,6 +1,7 @@ from typing import Callable, Iterable -from eth2spec.phase0 import spec +from eth2spec.phase0 import spec as spec_phase0 +from eth2spec.phase1 import spec as spec_phase1 from eth2spec.test.epoch_processing import ( test_process_crosslinks, test_process_registry_updates @@ -14,7 +15,8 @@ def create_suite(transition_name: str, config_name: str, get_cases: Callable[[], -> Callable[[str], gen_typing.TestSuiteOutput]: def suite_definition(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, config_name) - spec.apply_constants_preset(presets) + spec_phase0.apply_constants_preset(presets) + spec_phase1.apply_constants_preset(presets) return ("%s_%s" % (transition_name, config_name), transition_name, gen_suite.render_suite( title="%s epoch processing" % transition_name, diff --git a/test_generators/operations/main.py b/test_generators/operations/main.py index 0a487ae74..82e05b307 100644 --- a/test_generators/operations/main.py +++ b/test_generators/operations/main.py @@ -13,14 +13,16 @@ from eth2spec.test.block_processing import ( from gen_base import gen_runner, gen_suite, gen_typing from gen_from_tests.gen import generate_from_tests from preset_loader import loader -from eth2spec.phase0 import spec +from eth2spec.phase0 import spec as spec_phase0 +from eth2spec.phase1 import spec as spec_phase1 def create_suite(operation_name: str, config_name: str, get_cases: Callable[[], Iterable[gen_typing.TestCase]]) \ -> Callable[[str], gen_typing.TestSuiteOutput]: def suite_definition(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, config_name) - spec.apply_constants_preset(presets) + spec_phase0.apply_constants_preset(presets) + spec_phase1.apply_constants_preset(presets) return ("%s_%s" % (operation_name, config_name), operation_name, gen_suite.render_suite( title="%s operation" % operation_name, diff --git a/test_generators/sanity/main.py b/test_generators/sanity/main.py index bba6ed03d..a9c0fe160 100644 --- a/test_generators/sanity/main.py +++ b/test_generators/sanity/main.py @@ -5,14 +5,16 @@ from eth2spec.test.sanity import test_blocks, test_slots from gen_base import gen_runner, gen_suite, gen_typing from gen_from_tests.gen import generate_from_tests from preset_loader import loader -from eth2spec.phase0 import spec +from eth2spec.phase0 import spec as spec_phase0 +from eth2spec.phase1 import spec as spec_phase1 def create_suite(handler_name: str, config_name: str, get_cases: Callable[[], Iterable[gen_typing.TestCase]]) \ -> Callable[[str], gen_typing.TestSuiteOutput]: def suite_definition(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, config_name) - spec.apply_constants_preset(presets) + spec_phase0.apply_constants_preset(presets) + spec_phase1.apply_constants_preset(presets) return ("%sanity_s_%s" % (handler_name, config_name), handler_name, gen_suite.render_suite( title="sanity testing", diff --git a/test_generators/shuffling/main.py b/test_generators/shuffling/main.py index 711597189..862c4d910 100644 --- a/test_generators/shuffling/main.py +++ b/test_generators/shuffling/main.py @@ -1,4 +1,5 @@ -from eth2spec.phase0 import spec +from eth2spec.phase0 import spec as spec_phase0 +from eth2spec.phase1 import spec as spec_phase1 from eth_utils import ( to_dict, to_tuple ) @@ -22,7 +23,8 @@ def shuffling_test_cases(): def mini_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, 'minimal') - spec.apply_constants_preset(presets) + spec_phase0.apply_constants_preset(presets) + spec_phase1.apply_constants_preset(presets) return ("shuffling_minimal", "core", gen_suite.render_suite( title="Swap-or-Not Shuffling tests with minimal config", @@ -37,7 +39,8 @@ def mini_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: def full_shuffling_suite(configs_path: str) -> gen_typing.TestSuiteOutput: presets = loader.load_presets(configs_path, 'mainnet') - spec.apply_constants_preset(presets) + spec_phase0.apply_constants_preset(presets) + spec_phase1.apply_constants_preset(presets) return ("shuffling_full", "core", gen_suite.render_suite( title="Swap-or-Not Shuffling tests with mainnet config", diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index ece5f3ef5..587c37742 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -74,25 +74,25 @@ def test_empty_epoch_transition(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -@with_all_phases -@spec_state_test -def test_empty_epoch_transition_not_finalizing(spec, state): - # copy for later balance lookups. - pre_state = deepcopy(state) - yield 'pre', state +# @with_all_phases +# @spec_state_test +# def test_empty_epoch_transition_not_finalizing(spec, state): +# # copy for later balance lookups. +# pre_state = deepcopy(state) +# yield 'pre', state - block = build_empty_block_for_next_slot(spec, state) - block.slot += spec.SLOTS_PER_EPOCH * 5 - sign_block(spec, state, block, proposer_index=0) - yield 'blocks', [block], List[spec.BeaconBlock] +# block = build_empty_block_for_next_slot(spec, state) +# block.slot += spec.SLOTS_PER_EPOCH * 5 +# sign_block(spec, state, block, proposer_index=0) +# yield 'blocks', [block], List[spec.BeaconBlock] - spec.state_transition(state, block) - yield 'post', state +# spec.state_transition(state, block) +# yield 'post', state - assert state.slot == block.slot - assert state.finalized_epoch < spec.get_current_epoch(state) - 4 - for index in range(len(state.validator_registry)): - assert get_balance(state, index) < get_balance(pre_state, index) +# assert state.slot == block.slot +# assert state.finalized_epoch < spec.get_current_epoch(state) - 4 +# for index in range(len(state.validator_registry)): +# assert get_balance(state, index) < get_balance(pre_state, index) @with_all_phases @@ -381,29 +381,29 @@ def test_historical_batch(spec, state): assert len(state.historical_roots) == pre_historical_roots_len + 1 -@with_all_phases -@spec_state_test -def test_eth1_data_votes(spec, state): - yield 'pre', state +# @with_all_phases +# @spec_state_test +# def test_eth1_data_votes(spec, state): +# yield 'pre', state - expected_votes = 0 - assert len(state.eth1_data_votes) == expected_votes +# expected_votes = 0 +# assert len(state.eth1_data_votes) == expected_votes - blocks = [] - for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): - block = build_empty_block_for_next_slot(spec, state) - spec.state_transition(state, block) - expected_votes += 1 - assert len(state.eth1_data_votes) == expected_votes - blocks.append(block) +# blocks = [] +# for _ in range(spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1): +# block = build_empty_block_for_next_slot(spec, state) +# spec.state_transition(state, block) +# expected_votes += 1 +# assert len(state.eth1_data_votes) == expected_votes +# blocks.append(block) - block = build_empty_block_for_next_slot(spec, state) - blocks.append(block) +# block = build_empty_block_for_next_slot(spec, state) +# blocks.append(block) - spec.state_transition(state, block) +# spec.state_transition(state, block) - yield 'blocks', [block], List[spec.BeaconBlock] - yield 'post', state +# yield 'blocks', [block], List[spec.BeaconBlock] +# yield 'post', state - assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 - assert len(state.eth1_data_votes) == 1 +# assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 +# assert len(state.eth1_data_votes) == 1 From a7554d503c10d1bb423731486ae45c3d1258168a Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 5 Jun 2019 18:02:39 +0200 Subject: [PATCH 47/55] fix for typing check of vector elements with non-type element type (annotation) --- test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index 1e05ccd5d..8c2fc359c 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -1,4 +1,3 @@ -from inspect import isclass from typing import List, Iterable, TypeVar, Type, NewType from typing import Union from typing_inspect import get_origin @@ -247,8 +246,8 @@ class Vector(metaclass=VectorMeta): self.items = list(args) - # cannot check non-class objects - if isclass(cls.elem_type): + # cannot check non-type objects + if isinstance(cls.elem_type, type): for i, item in enumerate(self.items): if not isinstance(item, cls.elem_type): raise TypeError("Typed vector cannot hold differently typed value" From 1cc7c7309d25bd9c26c09824ec9898e8ee22e5dd Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 5 Jun 2019 18:28:09 +0200 Subject: [PATCH 48/55] change to issubclass, hope parametrized external type is ok --- test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index 8c2fc359c..4944fb600 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -249,7 +249,7 @@ class Vector(metaclass=VectorMeta): # cannot check non-type objects if isinstance(cls.elem_type, type): for i, item in enumerate(self.items): - if not isinstance(item, cls.elem_type): + if not issubclass(type(item), cls.elem_type): raise TypeError("Typed vector cannot hold differently typed value" " at index %d. Got type: %s, expected type: %s" % (i, type(item), cls.elem_type)) From b9abc5f2cf349cf0ec211458df36b86b92b42edf Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 5 Jun 2019 18:53:34 +0200 Subject: [PATCH 49/55] List[uint64] is not like a type but just for annotation, same for other Generics with __args__, Vector/BytesN work, because their metaclasses produce non-parametrized types, so don't check vector values when type contains args --- test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index 4944fb600..368041f90 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -246,8 +246,8 @@ class Vector(metaclass=VectorMeta): self.items = list(args) - # cannot check non-type objects - if isinstance(cls.elem_type, type): + # cannot check non-type objects, or parametrized types + if isinstance(cls.elem_type, type) and not hasattr(cls.elem_type, '__args__'): for i, item in enumerate(self.items): if not issubclass(type(item), cls.elem_type): raise TypeError("Typed vector cannot hold differently typed value" From e498ff7e94ee47ea69d390860a20c8d2a7061ca3 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 5 Jun 2019 21:28:30 +0200 Subject: [PATCH 50/55] Separates tests into phases --- .../eth2spec/test/{block_processing => phase_0}/__init__.py | 0 .../{epoch_processing => phase_0/block_processing}/__init__.py | 0 .../{ => phase_0}/block_processing/test_process_attestation.py | 0 .../block_processing/test_process_attester_slashing.py | 0 .../{ => phase_0}/block_processing/test_process_block_header.py | 0 .../test/{ => phase_0}/block_processing/test_process_deposit.py | 0 .../block_processing/test_process_proposer_slashing.py | 0 .../test/{ => phase_0}/block_processing/test_process_transfer.py | 0 .../{ => phase_0}/block_processing/test_process_voluntary_exit.py | 0 .../pyspec/eth2spec/test/phase_0/epoch_processing/__init__.py | 0 .../{ => phase_0}/epoch_processing/test_process_crosslinks.py | 0 .../epoch_processing/test_process_registry_updates.py | 0 test_libs/pyspec/eth2spec/test/phase_1/__init__.py | 0 .../pyspec/eth2spec/test/phase_1/block_processing/__init__.py | 0 .../block_processing/test_process_early_derived_secret_reveal.py | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename test_libs/pyspec/eth2spec/test/{block_processing => phase_0}/__init__.py (100%) rename test_libs/pyspec/eth2spec/test/{epoch_processing => phase_0/block_processing}/__init__.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_attestation.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_attester_slashing.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_block_header.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_deposit.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_proposer_slashing.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_transfer.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/block_processing/test_process_voluntary_exit.py (100%) create mode 100644 test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/__init__.py rename test_libs/pyspec/eth2spec/test/{ => phase_0}/epoch_processing/test_process_crosslinks.py (100%) rename test_libs/pyspec/eth2spec/test/{ => phase_0}/epoch_processing/test_process_registry_updates.py (100%) create mode 100644 test_libs/pyspec/eth2spec/test/phase_1/__init__.py create mode 100644 test_libs/pyspec/eth2spec/test/phase_1/block_processing/__init__.py rename test_libs/pyspec/eth2spec/test/{ => phase_1}/block_processing/test_process_early_derived_secret_reveal.py (100%) diff --git a/test_libs/pyspec/eth2spec/test/block_processing/__init__.py b/test_libs/pyspec/eth2spec/test/phase_0/__init__.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/__init__.py rename to test_libs/pyspec/eth2spec/test/phase_0/__init__.py diff --git a/test_libs/pyspec/eth2spec/test/epoch_processing/__init__.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/__init__.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/epoch_processing/__init__.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/__init__.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_attestation.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_attester_slashing.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_block_header.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_block_header.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_deposit.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_proposer_slashing.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_transfer.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_transfer.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_voluntary_exit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_voluntary_exit.py rename to test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/__init__.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/epoch_processing/test_process_crosslinks.py rename to test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py diff --git a/test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/epoch_processing/test_process_registry_updates.py rename to test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py diff --git a/test_libs/pyspec/eth2spec/test/phase_1/__init__.py b/test_libs/pyspec/eth2spec/test/phase_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/__init__.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py similarity index 100% rename from test_libs/pyspec/eth2spec/test/block_processing/test_process_early_derived_secret_reveal.py rename to test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py From 60d9dc68c4d95f28b50a1d144985b3a6cfdfd726 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Wed, 5 Jun 2019 21:42:55 +0200 Subject: [PATCH 51/55] Apply suggestions from @djrtwo's code review --- scripts/build_spec.py | 25 +- specs/core/0_beacon-chain.md | 2 + test_libs/pyspec/eth2spec/test/context.py | 4 +- .../test_process_attestation.py | 6 +- ...est_process_early_derived_secret_reveal.py | 8 +- .../pyspec/eth2spec/utils/minimal_ssz.py | 340 ------------------ 6 files changed, 26 insertions(+), 359 deletions(-) delete mode 100644 test_libs/pyspec/eth2spec/utils/minimal_ssz.py diff --git a/scripts/build_spec.py b/scripts/build_spec.py index 50d5955ee..7a51970e3 100644 --- a/scripts/build_spec.py +++ b/scripts/build_spec.py @@ -6,6 +6,7 @@ from function_puller import ( from argparse import ArgumentParser from typing import ( Dict, + List, Optional, ) @@ -122,13 +123,16 @@ def objects_to_spec(functions: Dict[str, str], constants: Dict[str, str], ssz_objects: Dict[str, str], inserts: Dict[str, str], - imports: Dict[str, str]) -> str: + imports: Dict[str, str], + new_types: Dict[str, str], + byte_types: List[int], + ) -> str: """ Given all the objects that constitute a spec, combine them into a single pyfile. """ new_type_definitions = \ - '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in NEW_TYPES.items()]) - new_type_definitions += '\n' + '\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(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types]) functions_spec = '\n\n'.join(functions.values()) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants)) ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values()) @@ -217,12 +221,11 @@ def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject: def build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]: functions, constants, ssz_objects, inserts = get_spec(sourcefile) - spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS) + spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS, NEW_TYPES, BYTE_TYPES) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) - else: - return spec + return spec def build_phase1_spec(phase0_sourcefile: str, @@ -235,12 +238,11 @@ def build_phase1_spec(phase0_sourcefile: str, spec_objects = phase0_spec for value in [phase1_custody, phase1_shard_data]: spec_objects = combine_spec_objects(spec_objects, value) - spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS) + spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, NEW_TYPES, BYTE_TYPES) if outfile is not None: with open(outfile, 'w') as out: out.write(spec) - else: - return spec + return spec if __name__ == '__main__': @@ -262,7 +264,10 @@ If building phase 1: args = parser.parse_args() if args.phase == 0: - build_phase0_spec(*args.files) + if len(args.files) == 2: + build_phase0_spec(*args.files) + else: + print(" Phase 0 requires an output as well as an input file.") elif args.phase == 1: if len(args.files) == 4: build_phase1_spec(*args.files) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index c58327d8d..a6d9d23c5 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1246,6 +1246,8 @@ def process_slot(state: BeaconState) -> None: ### Epoch processing +Note: the `# @LabelHere` lines below are placeholders to show that code will be inserted here in a future phase. + ```python def process_epoch(state: BeaconState) -> None: process_justification_and_finalization(state) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 046a71caa..8bfce8243 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -112,11 +112,11 @@ def with_phase1(fn): def with_all_phases(fn): """ - Decorator to run everything with all availible spec phases + Decorator to run everything with all available spec phases """ def entry(*args, **kw): kw['spec'] = spec_phase0 fn(*args, **kw) kw['spec'] = spec_phase1 - return fn(*args, **kw) + fn(*args, **kw) return entry diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 45cd604c5..8e214fe7d 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phase0 from eth2spec.test.helpers.attestations import ( get_valid_attestation, sign_attestation, @@ -214,7 +214,7 @@ def test_bad_source_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phase0 @spec_state_test def test_non_zero_crosslink_data_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -288,7 +288,7 @@ def test_inconsistent_bitfields(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phase0 @spec_state_test def test_non_empty_custody_bitfield(spec, state): attestation = get_valid_attestation(spec, state) diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py index c28c2e859..64440ef60 100644 --- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py @@ -1,6 +1,6 @@ -import pytest - from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal +from eth2spec.test.helpers.block import apply_empty_block +from eth2spec.test.helpers.state import next_epoch from eth2spec.test.context import with_phase1, spec_state_test, expect_assertion_error @@ -56,8 +56,8 @@ def test_reveal_from_current_epoch(spec, state): @with_phase1 @spec_state_test def test_reveal_from_past_epoch(spec, state): - if spec.get_current_epoch(state) < 1: - pytest.skip('testing of previous epoch requires epoch of at least 1') + next_epoch(spec, state) + apply_empty_block(spec, state) randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state) - 1) yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) diff --git a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py b/test_libs/pyspec/eth2spec/utils/minimal_ssz.py deleted file mode 100644 index 9a555af66..000000000 --- a/test_libs/pyspec/eth2spec/utils/minimal_ssz.py +++ /dev/null @@ -1,340 +0,0 @@ -from typing import Any - -from .hash_function import hash - -BYTES_PER_CHUNK = 32 -BYTES_PER_LENGTH_OFFSET = 4 -ZERO_CHUNK = b'\x00' * BYTES_PER_CHUNK - - -def SSZType(fields): - class SSZObject(): - def __init__(self, **kwargs): - for f, t in fields.items(): - if f not in kwargs: - setattr(self, f, get_zero_value(t)) - else: - setattr(self, f, kwargs[f]) - - def __eq__(self, other): - return self.fields == other.fields and self.serialize() == other.serialize() - - def __hash__(self): - return int.from_bytes(self.hash_tree_root(), byteorder="little") - - def __str__(self): - output = [] - for field in self.fields: - output.append(f'{field}: {getattr(self, field)}') - return "\n".join(output) - - def serialize(self): - return serialize_value(self, self.__class__) - - def hash_tree_root(self): - return hash_tree_root(self, self.__class__) - - SSZObject.fields = fields - return SSZObject - - -class Vector(): - def __init__(self, items): - self.items = items - self.length = len(items) - - def __getitem__(self, key): - return self.items[key] - - def __setitem__(self, key, value): - self.items[key] = value - - def __iter__(self): - return iter(self.items) - - def __len__(self): - return self.length - - -type_of = type - - -def empty(obj): - for field in obj.fields: - field = get_zero_value(field) - return obj - - -def is_basic(typ): - # if not a string, it is a complex, and cannot be basic - if not isinstance(typ, str): - return False - # "uintN": N-bit unsigned integer (where N in [8, 16, 32, 64, 128, 256]) - elif typ[:4] == 'uint' and typ[4:] in ['8', '16', '32', '64', '128', '256']: - return True - # "bool": True or False - elif typ == 'bool': - return True - # alias: "byte" -> "uint8" - elif typ == 'byte': - return True - # default - else: - return False - - -def is_constant_sized(typ): - # basic objects are fixed size by definition - if is_basic(typ): - return True - # dynamic size array type, "list": [elem_type]. - # Not constant size by definition. - elif isinstance(typ, list) and len(typ) == 1: - return False - # fixed size array type, "vector": [elem_type, length] - # Constant size, but only if the elements are. - elif isinstance(typ, list) and len(typ) == 2: - return is_constant_sized(typ[0]) - # bytes array (fixed or dynamic size) - elif isinstance(typ, str) and typ[:5] == 'bytes': - # if no length suffix, it has a dynamic size - return typ != 'bytes' - # containers are only constant-size if all of the fields are constant size. - elif hasattr(typ, 'fields'): - for subtype in typ.fields.values(): - if not is_constant_sized(subtype): - return False - return True - else: - raise Exception("Type not recognized") - - -def coerce_to_bytes(x): - if isinstance(x, str): - o = x.encode('utf-8') - assert len(o) == len(x) - return o - elif isinstance(x, bytes): - return x - else: - raise Exception("Expecting bytes") - - -def encode_series(values, types): - # Recursively serialize - parts = [(is_constant_sized(types[i]), serialize_value(values[i], types[i])) for i in range(len(values))] - - # Compute and check lengths - fixed_lengths = [len(serialized) if constant_size else BYTES_PER_LENGTH_OFFSET - for (constant_size, serialized) in parts] - variable_lengths = [len(serialized) if not constant_size else 0 - for (constant_size, serialized) in parts] - - # Check if integer is not out of bounds (Python) - assert sum(fixed_lengths + variable_lengths) < 2 ** (BYTES_PER_LENGTH_OFFSET * 8) - - # Interleave offsets of variable-size parts with fixed-size parts. - # Avoid quadratic complexity in calculation of offsets. - offset = sum(fixed_lengths) - variable_parts = [] - fixed_parts = [] - for (constant_size, serialized) in parts: - if constant_size: - fixed_parts.append(serialized) - else: - fixed_parts.append(offset.to_bytes(BYTES_PER_LENGTH_OFFSET, 'little')) - variable_parts.append(serialized) - offset += len(serialized) - - # Return the concatenation of the fixed-size parts (offsets interleaved) with the variable-size parts - return b"".join(fixed_parts + variable_parts) - - -def serialize_value(value, typ=None): - if typ is None: - typ = infer_type(value) - # "uintN" - if isinstance(typ, str) and typ[:4] == 'uint': - length = int(typ[4:]) - assert length in (8, 16, 32, 64, 128, 256) - return value.to_bytes(length // 8, 'little') - # "bool" - elif isinstance(typ, str) and typ == 'bool': - assert value in (True, False) - return b'\x01' if value is True else b'\x00' - # Vector - elif isinstance(typ, list) and len(typ) == 2: - # (regardless of element type, sanity-check if the length reported in the vector type matches the value length) - assert len(value) == typ[1] - return encode_series(value, [typ[0]] * len(value)) - # List - elif isinstance(typ, list) and len(typ) == 1: - return encode_series(value, [typ[0]] * len(value)) - # "bytes" (variable size) - elif isinstance(typ, str) and typ == 'bytes': - return coerce_to_bytes(value) - # "bytesN" (fixed size) - elif isinstance(typ, str) and len(typ) > 5 and typ[:5] == 'bytes': - assert len(value) == int(typ[5:]), (value, int(typ[5:])) - return coerce_to_bytes(value) - # containers - elif hasattr(typ, 'fields'): - values = [getattr(value, field) for field in typ.fields.keys()] - types = list(typ.fields.values()) - return encode_series(values, types) - else: - print(value, typ) - raise Exception("Type not recognized") - - -def get_zero_value(typ: Any) -> Any: - if isinstance(typ, str): - # Bytes array - if typ == 'bytes': - return b'' - # bytesN - elif typ[:5] == 'bytes' and len(typ) > 5: - length = int(typ[5:]) - return b'\x00' * length - # Basic types - elif typ == 'bool': - return False - elif typ[:4] == 'uint': - return 0 - elif typ == 'byte': - return 0x00 - else: - raise ValueError("Type not recognized") - # Vector: - elif isinstance(typ, list) and len(typ) == 2: - return [get_zero_value(typ[0]) for _ in range(typ[1])] - # List: - elif isinstance(typ, list) and len(typ) == 1: - return [] - # Container: - elif hasattr(typ, 'fields'): - return typ(**{field: get_zero_value(subtype) for field, subtype in typ.fields.items()}) - else: - print(typ) - raise Exception("Type not recognized") - - -def chunkify(bytez): - bytez += b'\x00' * (-len(bytez) % BYTES_PER_CHUNK) - return [bytez[i:i + 32] for i in range(0, len(bytez), 32)] - - -def pack(values, subtype): - return chunkify(b''.join([serialize_value(value, subtype) for value in values])) - - -def is_power_of_two(x): - return x > 0 and x & (x - 1) == 0 - - -def merkleize(chunks): - tree = chunks[::] - while not is_power_of_two(len(tree)): - tree.append(ZERO_CHUNK) - tree = [ZERO_CHUNK] * len(tree) + tree - for i in range(len(tree) // 2 - 1, 0, -1): - tree[i] = hash(tree[i * 2] + tree[i * 2 + 1]) - return tree[1] - - -def mix_in_length(root, length): - return hash(root + length.to_bytes(32, 'little')) - - -def infer_type(value): - """ - Note: defaults to uint64 for integer type inference due to lack of information. - Other integer sizes are still supported, see spec. - :param value: The value to infer a SSZ type for. - :return: The SSZ type. - """ - if hasattr(value.__class__, 'fields'): - return value.__class__ - elif isinstance(value, Vector): - if len(value) > 0: - return [infer_type(value[0]), len(value)] - else: - # Element type does not matter too much, - # assumed to be a basic type for size-encoding purposes, vector is empty. - return ['uint64'] - elif isinstance(value, list): - if len(value) > 0: - return [infer_type(value[0])] - else: - # Element type does not matter, list-content size will be encoded regardless, list is empty. - return ['uint64'] - elif isinstance(value, (bytes, str)): - return 'bytes' - elif isinstance(value, int): - return 'uint64' - else: - raise Exception("Failed to infer type") - - -def hash_tree_root(value, typ=None): - if typ is None: - typ = infer_type(value) - # ------------------------------------- - # merkleize(pack(value)) - # basic object: merkleize packed version (merkleization pads it to 32 bytes if it is not already) - if is_basic(typ): - return merkleize(pack([value], typ)) - # or a vector of basic objects - elif isinstance(typ, list) and len(typ) == 2 and is_basic(typ[0]): - assert len(value) == typ[1] - return merkleize(pack(value, typ[0])) - # ------------------------------------- - # mix_in_length(merkleize(pack(value)), len(value)) - # if value is a list of basic objects - elif isinstance(typ, list) and len(typ) == 1 and is_basic(typ[0]): - return mix_in_length(merkleize(pack(value, typ[0])), len(value)) - # (needs some extra work for non-fixed-sized bytes array) - elif typ == 'bytes': - return mix_in_length(merkleize(chunkify(coerce_to_bytes(value))), len(value)) - # ------------------------------------- - # merkleize([hash_tree_root(element) for element in value]) - # if value is a vector of composite objects - elif isinstance(typ, list) and len(typ) == 2 and not is_basic(typ[0]): - return merkleize([hash_tree_root(element, typ[0]) for element in value]) - # (needs some extra work for fixed-sized bytes array) - elif isinstance(typ, str) and typ[:5] == 'bytes' and len(typ) > 5: - assert len(value) == int(typ[5:]) - return merkleize(chunkify(coerce_to_bytes(value))) - # or a container - elif hasattr(typ, 'fields'): - return merkleize([hash_tree_root(getattr(value, field), subtype) for field, subtype in typ.fields.items()]) - # ------------------------------------- - # mix_in_length(merkleize([hash_tree_root(element) for element in value]), len(value)) - # if value is a list of composite objects - elif isinstance(typ, list) and len(typ) == 1 and not is_basic(typ[0]): - return mix_in_length(merkleize([hash_tree_root(element, typ[0]) for element in value]), len(value)) - # ------------------------------------- - else: - raise Exception("Type not recognized") - - -def truncate(container): - field_keys = list(container.fields.keys()) - truncated_fields = { - key: container.fields[key] - for key in field_keys[:-1] - } - truncated_class = SSZType(truncated_fields) - kwargs = { - field: getattr(container, field) - for field in field_keys[:-1] - } - return truncated_class(**kwargs) - - -def signing_root(container): - return hash_tree_root(truncate(container)) - - -def serialize(ssz_object): - return getattr(ssz_object, 'serialize')() From 4c1b9ef6d6fc3b844eeb9f7c8bff8c7a614ba48d Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 6 Jun 2019 11:04:55 +0200 Subject: [PATCH 52/55] Fixes custody key reveal test bug --- .../test_process_early_derived_secret_reveal.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py index 64440ef60..6c5785b2f 100644 --- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py @@ -1,6 +1,6 @@ from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal from eth2spec.test.helpers.block import apply_empty_block -from eth2spec.test.helpers.state import next_epoch +from eth2spec.test.helpers.state import next_epoch, get_balance from eth2spec.test.context import with_phase1, spec_state_test, expect_assertion_error @@ -19,6 +19,8 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v expect_assertion_error(lambda: spec.process_early_derived_secret_reveal(state, randao_key_reveal)) yield 'post', None return + + pre_slashed_balance = get_balance(state, randao_key_reveal.revealed_index) spec.process_early_derived_secret_reveal(state, randao_key_reveal) @@ -28,12 +30,8 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v assert slashed_validator.slashed assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH - # lost whistleblower reward - # FIXME: Currently broken because get_base_reward in genesis epoch is 0 - # assert ( - # state.balances[randao_key_reveal.revealed_index] < - # state.balances[randao_key_reveal.revealed_index] - # ) + + assert get_balance(state, randao_key_reveal.revealed_index) < pre_slashed_balance yield 'post', state From 35c03c5f3e7235630357dde8baf9f29224ee8500 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 6 Jun 2019 11:39:22 +0200 Subject: [PATCH 53/55] Adds review suggestions I missed --- configs/fork_timelines/mainnet.yaml | 2 +- specs/core/1_custody-game.md | 23 ++++++++++--------- specs/core/1_shard-data-chains.md | 13 ++++------- ...est_process_early_derived_secret_reveal.py | 2 +- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/configs/fork_timelines/mainnet.yaml b/configs/fork_timelines/mainnet.yaml index 8d51d6582..0bb3c9db1 100644 --- a/configs/fork_timelines/mainnet.yaml +++ b/configs/fork_timelines/mainnet.yaml @@ -7,6 +7,6 @@ phase0: 67108864 # phase0_funny_fork_name: 67116000 # Example 2: -# Should be equal to PHASE_1_GENESIS_EPOCH +# Should be equal to PHASE_1_FORK_EPOCH # (placeholder in example value here) # phase1: 67163000 diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index 954505c91..6c89ef853 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -372,7 +372,7 @@ def process_custody_key_reveal(state: BeaconState, # Reward Block Preposer proposer_index = get_beacon_proposer_index(state) - increase_balance(state, proposer_index, get_base_reward(state, proposer_index) // MINOR_REWARD_QUOTIENT) + increase_balance(state, proposer_index, get_base_reward(state, reveal.revealer_index) // MINOR_REWARD_QUOTIENT) ``` #### Early derived secret reveals @@ -462,7 +462,7 @@ For each `challenge` in `block.body.custody_chunk_challenges`, run the following def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge) -> None: # Verify the attestation - assert 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 assert slot_to_epoch(challenge.attestation.data.slot) >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY responder = state.validator_registry[challenge.responder_index] @@ -517,14 +517,15 @@ def process_bit_challenge(state: BeaconState, assert is_slashable_validator(challenger, get_current_epoch(state)) # Verify the attestation - assert validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation)) + attestation = challenge.attestation + validate_indexed_attestation(state, convert_to_indexed(state, attestation)) # Verify the attestation is eligible for challenging responder = state.validator_registry[challenge.responder_index] - assert (slot_to_epoch(challenge.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)) # Verify the responder participated in the attestation - attesters = get_attesting_indices(state, challenge.attestation.data, challenge.attestation.aggregation_bitfield) + attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield) assert challenge.responder_index in attesters # A validator can be the challenger for at most one challenge at a time @@ -536,7 +537,7 @@ def process_bit_challenge(state: BeaconState, get_validators_custody_reveal_period( state=state, index=challenge.responder_index, - epoch=slot_to_epoch(challenge.attestation.data.slot)), + epoch=slot_to_epoch(attestation.data.slot)), challenge.responder_index ) assert bls_verify( @@ -551,10 +552,10 @@ def process_bit_challenge(state: BeaconState, ) # Verify the chunk count - chunk_count = get_custody_chunk_count(challenge.attestation.data.crosslink) + chunk_count = get_custody_chunk_count(attestation.data.crosslink) assert verify_bitfield(challenge.chunk_bits, chunk_count) # Verify the first bit of the hash of the chunk bits does not equal the custody bit - custody_bit = get_bitfield_bit(challenge.attestation.custody_bitfield, attesters.index(challenge.responder_index)) + custody_bit = get_bitfield_bit(attestation.custody_bitfield, attesters.index(challenge.responder_index)) assert custody_bit != get_bitfield_bit(get_chunk_bits_root(challenge.chunk_bits), 0) # Add new bit challenge record new_record = CustodyBitChallengeRecord( @@ -562,7 +563,7 @@ def process_bit_challenge(state: BeaconState, challenger_index=challenge.challenger_index, responder_index=challenge.responder_index, inclusion_epoch=get_current_epoch(state), - data_root=challenge.attestation.data.crosslink.data_root, + data_root=attestation.data.crosslink.data_root, chunk_count=chunk_count, chunk_bits_merkle_root=hash_tree_root(challenge.chunk_bits), responder_key=challenge.responder_key, @@ -669,8 +670,8 @@ Run `process_reveal_deadlines(state)` immediately after `process_registry_update # end insert @process_reveal_deadlines def process_reveal_deadlines(state: BeaconState) -> None: for index, validator in enumerate(state.validator_registry): - if (validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) - < get_validators_custody_reveal_period(state, index)): + deadline = validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD) + if get_validators_custody_reveal_period(state, index) > deadline: slash_validator(state, index) ``` diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 044868209..21e08e7c9 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -46,8 +46,8 @@ This document describes the shard data layer and the shard fork choice rule in P | - | - | | `BYTES_PER_SHARD_BLOCK_BODY` | `2**14` (= 16,384) | | `MAX_SHARD_ATTESTIONS` | `2**4` (= 16) | -| `PHASE_1_GENESIS_EPOCH` | **TBD** | -| `PHASE_1_GENESIS_SLOT` | **TBD** | +| `PHASE_1_FORK_EPOCH` | **TBD** | +| `PHASE_1_FORK_SLOT` | **TBD** | | `GENESIS_SHARD_SLOT` | 0 | ### Time parameters @@ -274,14 +274,12 @@ Let: * `beacon_blocks` be the `BeaconBlock` list such that `beacon_blocks[slot]` is the canonical `BeaconBlock` at slot `slot` * `beacon_state` be the canonical `BeaconState` after processing `beacon_blocks[-1]` * `valid_shard_blocks` be the list of valid `ShardBlock`, recursively defined -* `unix_time` be the current unix time * `candidate` be a candidate `ShardBlock` for which validity is to be determined by running `is_valid_shard_block` ```python def is_valid_shard_block(beacon_blocks: List[BeaconBlock], beacon_state: BeaconState, valid_shard_blocks: List[ShardBlock], - unix_time: int, candidate: ShardBlock) -> bool: # Check if block is already determined valid for _, block in enumerate(valid_shard_blocks): @@ -289,8 +287,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], return True # Check slot number - assert candidate.slot >= PHASE_1_GENESIS_SLOT - assert unix_time >= beacon_state.genesis_time + (block.slot - GENESIS_SLOT) * SECONDS_PER_SLOT + assert candidate.slot >= PHASE_1_FORK_SLOT # Check shard number assert candidate.shard <= SHARD_COUNT @@ -304,7 +301,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], assert candidate.state_root == ZERO_HASH # [to be removed in phase 2] # Check parent block - if candidate.slot == PHASE_1_GENESIS_SLOT: + if candidate.slot == PHASE_1_FORK_SLOT: assert candidate.parent_root == ZERO_HASH else: parent_block = next( @@ -386,7 +383,7 @@ def is_valid_beacon_attestation(shard: Shard, return True # Check previous attestation - if candidate.data.previous_crosslink.epoch <= PHASE_1_GENESIS_EPOCH: + if candidate.data.previous_crosslink.epoch <= PHASE_1_FORK_EPOCH: assert candidate.data.previous_crosslink.data_root == ZERO_HASH else: previous_attestation = next( diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py index 6c5785b2f..30f19e031 100644 --- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py @@ -19,7 +19,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v expect_assertion_error(lambda: spec.process_early_derived_secret_reveal(state, randao_key_reveal)) yield 'post', None return - + pre_slashed_balance = get_balance(state, randao_key_reveal.revealed_index) spec.process_early_derived_secret_reveal(state, randao_key_reveal) From 956c476d81157195ac4fb313e4872a56f0a64508 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 6 Jun 2019 16:23:30 +0200 Subject: [PATCH 54/55] Move over to parameterised decorators for phases --- test_libs/pyspec/eth2spec/test/context.py | 40 ++++++------------- .../test_process_attestation.py | 40 +++++++++---------- .../test_process_attester_slashing.py | 20 +++++----- .../test_process_block_header.py | 12 +++--- .../block_processing/test_process_deposit.py | 18 ++++----- .../test_process_proposer_slashing.py | 22 +++++----- .../block_processing/test_process_transfer.py | 26 ++++++------ .../test_process_voluntary_exit.py | 18 ++++----- .../test_process_crosslinks.py | 10 ++--- .../test_process_registry_updates.py | 6 +-- ...est_process_early_derived_secret_reveal.py | 18 ++++----- .../eth2spec/test/sanity/test_blocks.py | 30 +++++++------- .../pyspec/eth2spec/test/sanity/test_slots.py | 12 +++--- .../pyspec/eth2spec/test/test_finality.py | 10 ++--- 14 files changed, 134 insertions(+), 148 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 8bfce8243..5dac3cefc 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -90,33 +90,19 @@ def bls_switch(fn): return entry -def with_phase0(fn): +def with_phases(phases): """ - Decorator to use phase 0's spec. + Decorator factory that returns a decorator that runs a test for the appropriate phases """ - def entry(*args, **kw): - kw['spec'] = spec_phase0 - return fn(*args, **kw) - return entry + def decorator(fn): + def run_with_spec_version(spec, *args, **kw): + kw['spec'] = spec + fn(*args, **kw) - -def with_phase1(fn): - """ - Decorator to use phase 1's spec - """ - def entry(*args, **kw): - kw['spec'] = spec_phase1 - return fn(*args, **kw) - return entry - - -def with_all_phases(fn): - """ - Decorator to run everything with all available spec phases - """ - def entry(*args, **kw): - kw['spec'] = spec_phase0 - fn(*args, **kw) - kw['spec'] = spec_phase1 - fn(*args, **kw) - return entry + def wrapper(*args, **kw): + if 'phase0' in phases: + run_with_spec_version(spec_phase0, *args, **kw) + if 'phase1' in phases: + run_with_spec_version(spec_phase1, *args, **kw) + return wrapper + return decorator diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 8e214fe7d..7840345b6 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phase0 +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.attestations import ( get_valid_attestation, sign_attestation, @@ -47,7 +47,7 @@ def run_attestation_processing(spec, state, attestation, valid=True): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -56,7 +56,7 @@ def test_success(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -66,7 +66,7 @@ def test_success_previous_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_since_max_epochs_per_crosslink(spec, state): for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): @@ -85,7 +85,7 @@ def test_success_since_max_epochs_per_crosslink(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_attestation_signature(spec, state): @@ -95,7 +95,7 @@ def test_invalid_attestation_signature(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_before_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -104,7 +104,7 @@ def test_before_inclusion_delay(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_after_epoch_slots(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -115,7 +115,7 @@ def test_after_epoch_slots(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_old_source_epoch(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 @@ -135,7 +135,7 @@ def test_old_source_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_wrong_shard(spec, state): attestation = get_valid_attestation(spec, state) @@ -148,7 +148,7 @@ def test_wrong_shard(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_new_source_epoch(spec, state): attestation = get_valid_attestation(spec, state) @@ -161,7 +161,7 @@ def test_new_source_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_source_root_is_target_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -174,7 +174,7 @@ def test_source_root_is_target_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_current_source_root(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 @@ -201,7 +201,7 @@ def test_invalid_current_source_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_bad_source_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -214,7 +214,7 @@ def test_bad_source_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phase0 +@with_phases(['phase0']) @spec_state_test def test_non_zero_crosslink_data_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -227,7 +227,7 @@ def test_non_zero_crosslink_data_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_bad_parent_crosslink(spec, state): next_epoch(spec, state) @@ -243,7 +243,7 @@ def test_bad_parent_crosslink(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_bad_crosslink_start_epoch(spec, state): next_epoch(spec, state) @@ -259,7 +259,7 @@ def test_bad_crosslink_start_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_bad_crosslink_end_epoch(spec, state): next_epoch(spec, state) @@ -275,7 +275,7 @@ def test_bad_crosslink_end_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_inconsistent_bitfields(spec, state): attestation = get_valid_attestation(spec, state) @@ -288,7 +288,7 @@ def test_inconsistent_bitfields(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phase0 +@with_phases(['phase0']) @spec_state_test def test_non_empty_custody_bitfield(spec, state): attestation = get_valid_attestation(spec, state) @@ -301,7 +301,7 @@ def test_non_empty_custody_bitfield(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_empty_aggregation_bitfield(spec, state): attestation = get_valid_attestation(spec, state) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index 6c7637d59..aad68cc4b 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.attestations import sign_indexed_attestation from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing from eth2spec.test.helpers.block import apply_empty_block @@ -54,7 +54,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True) yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_double(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) @@ -62,7 +62,7 @@ def test_success_double(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_surround(spec, state): next_epoch(spec, state) @@ -80,7 +80,7 @@ def test_success_surround(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_1(spec, state): @@ -88,7 +88,7 @@ def test_invalid_sig_1(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_2(spec, state): @@ -96,7 +96,7 @@ def test_invalid_sig_2(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_1_and_2(spec, state): @@ -104,7 +104,7 @@ def test_invalid_sig_1_and_2(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_same_data(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) @@ -115,7 +115,7 @@ def test_same_data(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_no_double_or_surround(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) @@ -126,7 +126,7 @@ def test_no_double_or_surround(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_participants_already_slashed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) @@ -140,7 +140,7 @@ def test_participants_already_slashed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_custody_bit_0_and_1(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py index f3c017982..b2d22232f 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, sign_block @@ -34,14 +34,14 @@ def run_block_header_processing(spec, state, block, valid=True): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_block_header(spec, state): block = build_empty_block_for_next_slot(spec, state, signed=True) yield from run_block_header_processing(spec, state, block) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_block_header(spec, state): @@ -49,7 +49,7 @@ def test_invalid_sig_block_header(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_slot_block_header(spec, state): block = build_empty_block_for_next_slot(spec, state) @@ -59,7 +59,7 @@ def test_invalid_slot_block_header(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_parent_root(spec, state): block = build_empty_block_for_next_slot(spec, state) @@ -69,7 +69,7 @@ def test_invalid_parent_root(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_proposer_slashed(spec, state): # use stub state to get proposer index of next slot diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py index c50b11f2e..302a3d37f 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.deposits import ( build_deposit, prepare_state_and_deposit, @@ -52,7 +52,7 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef assert state.deposit_index == state.latest_eth1_data.deposit_count -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_new_deposit(spec, state): # fresh deposit = next validator index = validator appended to registry @@ -63,7 +63,7 @@ def test_new_deposit(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_new_deposit(spec, state): @@ -74,7 +74,7 @@ def test_invalid_sig_new_deposit(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_top_up(spec, state): validator_index = 0 @@ -84,7 +84,7 @@ def test_success_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_top_up(spec, state): @@ -96,7 +96,7 @@ def test_invalid_sig_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_withdrawal_credentials_top_up(spec, state): validator_index = 0 @@ -114,7 +114,7 @@ def test_invalid_withdrawal_credentials_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_wrong_index(spec, state): validator_index = len(state.validator_registry) @@ -129,7 +129,7 @@ def test_wrong_index(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_wrong_deposit_for_deposit_count(spec, state): deposit_data_leaves = [spec.ZERO_HASH] * len(state.validator_registry) @@ -175,7 +175,7 @@ def test_wrong_deposit_for_deposit_count(spec, state): # TODO: test invalid signature -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_bad_merkle_proof(spec, state): validator_index = len(state.validator_registry) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py index b35241859..3c8e20d7e 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.block_header import sign_block_header from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing @@ -40,7 +40,7 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True) ) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -48,7 +48,7 @@ def test_success(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_1(spec, state): @@ -56,7 +56,7 @@ def test_invalid_sig_1(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_2(spec, state): @@ -64,7 +64,7 @@ def test_invalid_sig_2(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_sig_1_and_2(spec, state): @@ -72,7 +72,7 @@ def test_invalid_sig_1_and_2(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_proposer_index(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -82,7 +82,7 @@ def test_invalid_proposer_index(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_epochs_are_different(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) @@ -94,7 +94,7 @@ def test_epochs_are_different(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_headers_are_same(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) @@ -105,7 +105,7 @@ def test_headers_are_same(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_proposer_is_not_activated(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -116,7 +116,7 @@ def test_proposer_is_not_activated(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_proposer_is_slashed(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -127,7 +127,7 @@ def test_proposer_is_slashed(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_proposer_is_withdrawn(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py index 1294ca84a..13de5f6b0 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.state import next_epoch from eth2spec.test.helpers.block import apply_empty_block from eth2spec.test.helpers.transfers import get_valid_transfer @@ -36,7 +36,7 @@ def run_transfer_processing(spec, state, transfer, valid=True): assert state.balances[proposer_index] == pre_transfer_proposer_balance + transfer.fee -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_non_activated(spec, state): transfer = get_valid_transfer(spec, state, signed=True) @@ -46,7 +46,7 @@ def test_success_non_activated(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_withdrawable(spec, state): next_epoch(spec, state) @@ -60,7 +60,7 @@ def test_success_withdrawable(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_active_above_max_effective(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -70,7 +70,7 @@ def test_success_active_above_max_effective(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_active_above_max_effective_fee(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -80,7 +80,7 @@ def test_success_active_above_max_effective_fee(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_signature(spec, state): @@ -91,7 +91,7 @@ def test_invalid_signature(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_active_but_transfer_past_effective_balance(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -102,7 +102,7 @@ def test_active_but_transfer_past_effective_balance(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_incorrect_slot(spec, state): transfer = get_valid_transfer(spec, state, slot=state.slot + 1, signed=True) @@ -112,7 +112,7 @@ def test_incorrect_slot(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_insufficient_balance_for_fee(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -125,7 +125,7 @@ def test_insufficient_balance_for_fee(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_insufficient_balance(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -138,7 +138,7 @@ def test_insufficient_balance(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_no_dust_sender(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -158,7 +158,7 @@ def test_no_dust_sender(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_no_dust_recipient(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -172,7 +172,7 @@ def test_no_dust_recipient(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_invalid_pubkey(spec, state): transfer = get_valid_transfer(spec, state, signed=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py index 3359c5e78..4b3f7446c 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases from eth2spec.test.helpers.keys import pubkey_to_privkey from eth2spec.test.helpers.voluntary_exits import build_voluntary_exit, sign_voluntary_exit @@ -31,7 +31,7 @@ def run_voluntary_exit_processing(spec, state, voluntary_exit, valid=True): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -46,7 +46,7 @@ def test_success(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit) -@with_all_phases +@with_phases(['phase0', 'phase1']) @always_bls @spec_state_test def test_invalid_signature(spec, state): @@ -62,7 +62,7 @@ def test_invalid_signature(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_success_exit_queue(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -114,7 +114,7 @@ def test_success_exit_queue(spec, state): ) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_validator_exit_in_future(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -138,7 +138,7 @@ def test_validator_exit_in_future(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_validator_invalid_validator_index(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -162,7 +162,7 @@ def test_validator_invalid_validator_index(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_validator_not_active(spec, state): current_epoch = spec.get_current_epoch(state) @@ -184,7 +184,7 @@ def test_validator_not_active(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_validator_already_exited(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit @@ -209,7 +209,7 @@ def test_validator_already_exited(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_validator_not_active_long_enough(spec, state): current_epoch = spec.get_current_epoch(state) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py index 65d958678..65bb6a055 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, with_all_phases +from eth2spec.test.context import spec_state_test, with_phases from eth2spec.test.helpers.state import ( next_epoch, next_slot @@ -37,7 +37,7 @@ def run_process_crosslinks(spec, state, valid=True): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_no_attestations(spec, state): yield from run_process_crosslinks(spec, state) @@ -46,7 +46,7 @@ def test_no_attestations(spec, state): assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_single_crosslink_update_from_current_epoch(spec, state): next_epoch(spec, state) @@ -67,7 +67,7 @@ def test_single_crosslink_update_from_current_epoch(spec, state): assert pre_crosslink != state.current_crosslinks[shard] -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_single_crosslink_update_from_previous_epoch(spec, state): next_epoch(spec, state) @@ -98,7 +98,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state): assert crosslink_deltas[1][index] == 0 -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_double_late_crosslink(spec, state): if spec.get_epoch_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index e6679f844..daa52dba9 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -1,7 +1,7 @@ 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.state import next_epoch -from eth2spec.test.context import spec_state_test, with_all_phases +from eth2spec.test.context import spec_state_test, with_phases def run_process_registry_updates(spec, state, valid=True): @@ -31,7 +31,7 @@ def run_process_registry_updates(spec, state, valid=True): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_activation(spec, state): index = 0 @@ -56,7 +56,7 @@ def test_activation(spec, state): ) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_ejection(spec, state): index = 0 diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py index 30f19e031..f028217c6 100644 --- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py @@ -1,7 +1,7 @@ from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal from eth2spec.test.helpers.block import apply_empty_block from eth2spec.test.helpers.state import next_epoch, get_balance -from eth2spec.test.context import with_phase1, spec_state_test, expect_assertion_error +from eth2spec.test.context import with_phases, spec_state_test, expect_assertion_error def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, valid=True): @@ -35,7 +35,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v yield 'post', state -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_success(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state) @@ -43,7 +43,7 @@ def test_success(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_reveal_from_current_epoch(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state)) @@ -51,7 +51,7 @@ def test_reveal_from_current_epoch(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_reveal_from_past_epoch(spec, state): next_epoch(spec, state) @@ -61,7 +61,7 @@ def test_reveal_from_past_epoch(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_reveal_with_custody_padding(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( @@ -72,7 +72,7 @@ def test_reveal_with_custody_padding(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_reveal_with_custody_padding_minus_one(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( @@ -83,7 +83,7 @@ def test_reveal_with_custody_padding_minus_one(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_double_reveal(spec, state): randao_key_reveal1 = get_valid_early_derived_secret_reveal( @@ -107,7 +107,7 @@ def test_double_reveal(spec, state): yield 'post', post_state -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_revealer_is_slashed(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state)) @@ -116,7 +116,7 @@ def test_revealer_is_slashed(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phase1 +@with_phases(['phase1']) @spec_state_test def test_far_future_epoch(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index 587c37742..c08dd83cd 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -13,10 +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.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, never_bls, with_phases -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_empty_block_transition(spec, state): @@ -35,7 +35,7 @@ def test_empty_block_transition(spec, state): assert spec.get_block_root_at_slot(state, pre_slot) == block.parent_root -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_skipped_slots(spec, state): @@ -55,7 +55,7 @@ def test_skipped_slots(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_empty_epoch_transition(spec, state): pre_slot = state.slot @@ -74,7 +74,7 @@ def test_empty_epoch_transition(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -# @with_all_phases +# @with_phases(['phase0', 'phase1']) # @spec_state_test # def test_empty_epoch_transition_not_finalizing(spec, state): # # copy for later balance lookups. @@ -95,7 +95,7 @@ def test_empty_epoch_transition(spec, state): # assert get_balance(state, index) < get_balance(pre_state, index) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_proposer_slashing(spec, state): # copy for later balance lookups. @@ -127,7 +127,7 @@ def test_proposer_slashing(spec, state): assert get_balance(state, validator_index) < get_balance(pre_state, validator_index) -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_attester_slashing(spec, state): # copy for later balance lookups. @@ -169,7 +169,7 @@ def test_attester_slashing(spec, state): # TODO update functions below to be like above, i.e. with @spec_state_test and yielding data to put into the test vector -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_deposit_in_block(spec, state): initial_registry_len = len(state.validator_registry) @@ -196,7 +196,7 @@ def test_deposit_in_block(spec, state): assert state.validator_registry[validator_index].pubkey == pubkeys[validator_index] -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_deposit_top_up(spec, state): validator_index = 0 @@ -223,7 +223,7 @@ def test_deposit_top_up(spec, state): assert get_balance(state, validator_index) == validator_pre_balance + amount -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_attestation(spec, state): state.slot = spec.SLOTS_PER_EPOCH @@ -257,7 +257,7 @@ def test_attestation(spec, state): assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_voluntary_exit(spec, state): validator_index = spec.get_active_validator_indices( @@ -303,7 +303,7 @@ def test_voluntary_exit(spec, state): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_transfer(spec, state): # overwrite default 0 to test @@ -337,7 +337,7 @@ def test_transfer(spec, state): assert recipient_balance == pre_transfer_recipient_balance + amount -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_balance_driven_status_transitions(spec, state): current_epoch = spec.get_current_epoch(state) @@ -362,7 +362,7 @@ def test_balance_driven_status_transitions(spec, state): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_historical_batch(spec, state): state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1 @@ -381,7 +381,7 @@ def test_historical_batch(spec, state): assert len(state.historical_roots) == pre_historical_roots_len + 1 -# @with_all_phases +# @with_phases(['phase0', 'phase1']) # @spec_state_test # def test_eth1_data_votes(spec, state): # yield 'pre', state diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_slots.py b/test_libs/pyspec/eth2spec/test/sanity/test_slots.py index 6ef6be4d3..feddd65be 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_slots.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_slots.py @@ -1,8 +1,8 @@ from eth2spec.test.helpers.state import get_state_root -from eth2spec.test.context import spec_state_test, with_all_phases +from eth2spec.test.context import spec_state_test, with_phases -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_slots_1(spec, state): pre_slot = state.slot @@ -18,7 +18,7 @@ def test_slots_1(spec, state): assert get_state_root(spec, state, pre_slot) == pre_root -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_slots_2(spec, state): yield 'pre', state @@ -28,7 +28,7 @@ def test_slots_2(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_empty_epoch(spec, state): yield 'pre', state @@ -38,7 +38,7 @@ def test_empty_epoch(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_double_empty_epoch(spec, state): yield 'pre', state @@ -48,7 +48,7 @@ def test_double_empty_epoch(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @spec_state_test def test_over_epoch_boundary(spec, state): spec.process_slots(state, state.slot + (spec.SLOTS_PER_EPOCH // 2)) diff --git a/test_libs/pyspec/eth2spec/test/test_finality.py b/test_libs/pyspec/eth2spec/test/test_finality.py index 801e8b4fd..2d2e01432 100644 --- a/test_libs/pyspec/eth2spec/test/test_finality.py +++ b/test_libs/pyspec/eth2spec/test/test_finality.py @@ -1,7 +1,7 @@ from copy import deepcopy 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_phases from eth2spec.test.helpers.state import next_epoch from eth2spec.test.helpers.block import build_empty_block_for_next_slot, apply_empty_block from eth2spec.test.helpers.attestations import get_valid_attestation @@ -60,7 +60,7 @@ def next_epoch_with_attestations(spec, return state, blocks, post_state -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_finality_rule_4(spec, state): @@ -89,7 +89,7 @@ def test_finality_rule_4(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_finality_rule_1(spec, state): @@ -120,7 +120,7 @@ def test_finality_rule_1(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_finality_rule_2(spec, state): @@ -153,7 +153,7 @@ def test_finality_rule_2(spec, state): yield 'post', state -@with_all_phases +@with_phases(['phase0', 'phase1']) @never_bls @spec_state_test def test_finality_rule_3(spec, state): From 67471a8d6e802115513c4014fa25c6abd28c7f35 Mon Sep 17 00:00:00 2001 From: Carl Beekhuizen Date: Thu, 6 Jun 2019 23:30:40 +0200 Subject: [PATCH 55/55] Rework of phases decorator --- test_libs/pyspec/eth2spec/test/context.py | 19 ++++++++++ .../test_process_attestation.py | 36 +++++++++---------- .../test_process_attester_slashing.py | 20 +++++------ .../test_process_block_header.py | 12 +++---- .../block_processing/test_process_deposit.py | 18 +++++----- .../test_process_proposer_slashing.py | 22 ++++++------ .../block_processing/test_process_transfer.py | 26 +++++++------- .../test_process_voluntary_exit.py | 18 +++++----- .../test_process_crosslinks.py | 10 +++--- .../test_process_registry_updates.py | 6 ++-- ...est_process_early_derived_secret_reveal.py | 18 +++++----- .../eth2spec/test/sanity/test_blocks.py | 30 ++++++++-------- .../pyspec/eth2spec/test/sanity/test_slots.py | 12 +++---- .../pyspec/eth2spec/test/test_finality.py | 10 +++--- 14 files changed, 138 insertions(+), 119 deletions(-) diff --git a/test_libs/pyspec/eth2spec/test/context.py b/test_libs/pyspec/eth2spec/test/context.py index 5dac3cefc..cbc594cd8 100644 --- a/test_libs/pyspec/eth2spec/test/context.py +++ b/test_libs/pyspec/eth2spec/test/context.py @@ -90,6 +90,25 @@ def bls_switch(fn): return entry +all_phases = ['phase0', 'phase1'] + + +def with_all_phases(fn): + """ + A decorator for running a test wil every phase + """ + return with_phases(all_phases)(fn) + + +def with_all_phases_except(exclusion_phases): + """ + A decorator factory for running a tests with every phase except the ones listed + """ + def decorator(fn): + return with_phases([phase for phase in all_phases if phase not in exclusion_phases])(fn) + return decorator + + def with_phases(phases): """ Decorator factory that returns a decorator that runs a test for the appropriate phases diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py index 7840345b6..2b34ab405 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attestation.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases, with_phases from eth2spec.test.helpers.attestations import ( get_valid_attestation, sign_attestation, @@ -47,7 +47,7 @@ def run_attestation_processing(spec, state, attestation, valid=True): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -56,7 +56,7 @@ def test_success(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -66,7 +66,7 @@ def test_success_previous_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_since_max_epochs_per_crosslink(spec, state): for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): @@ -85,7 +85,7 @@ def test_success_since_max_epochs_per_crosslink(spec, state): yield from run_attestation_processing(spec, state, attestation) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_attestation_signature(spec, state): @@ -95,7 +95,7 @@ def test_invalid_attestation_signature(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_before_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -104,7 +104,7 @@ def test_before_inclusion_delay(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_after_epoch_slots(spec, state): attestation = get_valid_attestation(spec, state, signed=True) @@ -115,7 +115,7 @@ def test_after_epoch_slots(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_old_source_epoch(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 @@ -135,7 +135,7 @@ def test_old_source_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_wrong_shard(spec, state): attestation = get_valid_attestation(spec, state) @@ -148,7 +148,7 @@ def test_wrong_shard(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_new_source_epoch(spec, state): attestation = get_valid_attestation(spec, state) @@ -161,7 +161,7 @@ def test_new_source_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_source_root_is_target_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -174,7 +174,7 @@ def test_source_root_is_target_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_current_source_root(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 @@ -201,7 +201,7 @@ def test_invalid_current_source_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_bad_source_root(spec, state): attestation = get_valid_attestation(spec, state) @@ -227,7 +227,7 @@ def test_non_zero_crosslink_data_root(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_bad_parent_crosslink(spec, state): next_epoch(spec, state) @@ -243,7 +243,7 @@ def test_bad_parent_crosslink(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_bad_crosslink_start_epoch(spec, state): next_epoch(spec, state) @@ -259,7 +259,7 @@ def test_bad_crosslink_start_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_bad_crosslink_end_epoch(spec, state): next_epoch(spec, state) @@ -275,7 +275,7 @@ def test_bad_crosslink_end_epoch(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_inconsistent_bitfields(spec, state): attestation = get_valid_attestation(spec, state) @@ -301,7 +301,7 @@ def test_non_empty_custody_bitfield(spec, state): yield from run_attestation_processing(spec, state, attestation, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_empty_aggregation_bitfield(spec, state): attestation = get_valid_attestation(spec, state) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py index aad68cc4b..6c7637d59 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.attestations import sign_indexed_attestation from eth2spec.test.helpers.attester_slashings import get_valid_attester_slashing from eth2spec.test.helpers.block import apply_empty_block @@ -54,7 +54,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True) yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_double(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) @@ -62,7 +62,7 @@ def test_success_double(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_surround(spec, state): next_epoch(spec, state) @@ -80,7 +80,7 @@ def test_success_surround(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_1(spec, state): @@ -88,7 +88,7 @@ def test_invalid_sig_1(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_2(spec, state): @@ -96,7 +96,7 @@ def test_invalid_sig_2(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_1_and_2(spec, state): @@ -104,7 +104,7 @@ def test_invalid_sig_1_and_2(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_same_data(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) @@ -115,7 +115,7 @@ def test_same_data(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_no_double_or_surround(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) @@ -126,7 +126,7 @@ def test_no_double_or_surround(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_participants_already_slashed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) @@ -140,7 +140,7 @@ def test_participants_already_slashed(spec, state): yield from run_attester_slashing_processing(spec, state, attester_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_custody_bit_0_and_1(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py index b2d22232f..f3c017982 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, sign_block @@ -34,14 +34,14 @@ def run_block_header_processing(spec, state, block, valid=True): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_block_header(spec, state): block = build_empty_block_for_next_slot(spec, state, signed=True) yield from run_block_header_processing(spec, state, block) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_block_header(spec, state): @@ -49,7 +49,7 @@ def test_invalid_sig_block_header(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_slot_block_header(spec, state): block = build_empty_block_for_next_slot(spec, state) @@ -59,7 +59,7 @@ def test_invalid_slot_block_header(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_parent_root(spec, state): block = build_empty_block_for_next_slot(spec, state) @@ -69,7 +69,7 @@ def test_invalid_parent_root(spec, state): yield from run_block_header_processing(spec, state, block, valid=False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_proposer_slashed(spec, state): # use stub state to get proposer index of next slot diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py index 302a3d37f..c50b11f2e 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.deposits import ( build_deposit, prepare_state_and_deposit, @@ -52,7 +52,7 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef assert state.deposit_index == state.latest_eth1_data.deposit_count -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_new_deposit(spec, state): # fresh deposit = next validator index = validator appended to registry @@ -63,7 +63,7 @@ def test_new_deposit(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_new_deposit(spec, state): @@ -74,7 +74,7 @@ def test_invalid_sig_new_deposit(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_top_up(spec, state): validator_index = 0 @@ -84,7 +84,7 @@ def test_success_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_top_up(spec, state): @@ -96,7 +96,7 @@ def test_invalid_sig_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_withdrawal_credentials_top_up(spec, state): validator_index = 0 @@ -114,7 +114,7 @@ def test_invalid_withdrawal_credentials_top_up(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_wrong_index(spec, state): validator_index = len(state.validator_registry) @@ -129,7 +129,7 @@ def test_wrong_index(spec, state): yield from run_deposit_processing(spec, state, deposit, validator_index, valid=False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_wrong_deposit_for_deposit_count(spec, state): deposit_data_leaves = [spec.ZERO_HASH] * len(state.validator_registry) @@ -175,7 +175,7 @@ def test_wrong_deposit_for_deposit_count(spec, state): # TODO: test invalid signature -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_bad_merkle_proof(spec, state): validator_index = len(state.validator_registry) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py index 3c8e20d7e..b35241859 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.block_header import sign_block_header from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing @@ -40,7 +40,7 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True) ) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -48,7 +48,7 @@ def test_success(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_1(spec, state): @@ -56,7 +56,7 @@ def test_invalid_sig_1(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_2(spec, state): @@ -64,7 +64,7 @@ def test_invalid_sig_2(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_sig_1_and_2(spec, state): @@ -72,7 +72,7 @@ def test_invalid_sig_1_and_2(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_proposer_index(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -82,7 +82,7 @@ def test_invalid_proposer_index(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_epochs_are_different(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) @@ -94,7 +94,7 @@ def test_epochs_are_different(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_headers_are_same(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=False) @@ -105,7 +105,7 @@ def test_headers_are_same(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_proposer_is_not_activated(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -116,7 +116,7 @@ def test_proposer_is_not_activated(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_proposer_is_slashed(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) @@ -127,7 +127,7 @@ def test_proposer_is_slashed(spec, state): yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_proposer_is_withdrawn(spec, state): proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py index 13de5f6b0..1294ca84a 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.state import next_epoch from eth2spec.test.helpers.block import apply_empty_block from eth2spec.test.helpers.transfers import get_valid_transfer @@ -36,7 +36,7 @@ def run_transfer_processing(spec, state, transfer, valid=True): assert state.balances[proposer_index] == pre_transfer_proposer_balance + transfer.fee -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_non_activated(spec, state): transfer = get_valid_transfer(spec, state, signed=True) @@ -46,7 +46,7 @@ def test_success_non_activated(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_withdrawable(spec, state): next_epoch(spec, state) @@ -60,7 +60,7 @@ def test_success_withdrawable(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_active_above_max_effective(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -70,7 +70,7 @@ def test_success_active_above_max_effective(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_active_above_max_effective_fee(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -80,7 +80,7 @@ def test_success_active_above_max_effective_fee(spec, state): yield from run_transfer_processing(spec, state, transfer) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_signature(spec, state): @@ -91,7 +91,7 @@ def test_invalid_signature(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_active_but_transfer_past_effective_balance(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -102,7 +102,7 @@ def test_active_but_transfer_past_effective_balance(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_incorrect_slot(spec, state): transfer = get_valid_transfer(spec, state, slot=state.slot + 1, signed=True) @@ -112,7 +112,7 @@ def test_incorrect_slot(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_insufficient_balance_for_fee(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -125,7 +125,7 @@ def test_insufficient_balance_for_fee(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_insufficient_balance(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -138,7 +138,7 @@ def test_insufficient_balance(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_no_dust_sender(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -158,7 +158,7 @@ def test_no_dust_sender(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_no_dust_recipient(spec, state): sender_index = spec.get_active_validator_indices(state, spec.get_current_epoch(state))[-1] @@ -172,7 +172,7 @@ def test_no_dust_recipient(spec, state): yield from run_transfer_processing(spec, state, transfer, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_invalid_pubkey(spec, state): transfer = get_valid_transfer(spec, state, signed=True) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py index 4b3f7446c..3359c5e78 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py @@ -1,4 +1,4 @@ -from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_phases +from eth2spec.test.context import spec_state_test, expect_assertion_error, always_bls, with_all_phases from eth2spec.test.helpers.keys import pubkey_to_privkey from eth2spec.test.helpers.voluntary_exits import build_voluntary_exit, sign_voluntary_exit @@ -31,7 +31,7 @@ def run_voluntary_exit_processing(spec, state, voluntary_exit, valid=True): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -46,7 +46,7 @@ def test_success(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit) -@with_phases(['phase0', 'phase1']) +@with_all_phases @always_bls @spec_state_test def test_invalid_signature(spec, state): @@ -62,7 +62,7 @@ def test_invalid_signature(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_success_exit_queue(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -114,7 +114,7 @@ def test_success_exit_queue(spec, state): ) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_validator_exit_in_future(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -138,7 +138,7 @@ def test_validator_exit_in_future(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_validator_invalid_validator_index(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit @@ -162,7 +162,7 @@ def test_validator_invalid_validator_index(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_validator_not_active(spec, state): current_epoch = spec.get_current_epoch(state) @@ -184,7 +184,7 @@ def test_validator_not_active(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_validator_already_exited(spec, state): # move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow validator able to exit @@ -209,7 +209,7 @@ def test_validator_already_exited(spec, state): yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_validator_not_active_long_enough(spec, state): current_epoch = spec.get_current_epoch(state) diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py index 65bb6a055..65d958678 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_crosslinks.py @@ -1,6 +1,6 @@ from copy import deepcopy -from eth2spec.test.context import spec_state_test, with_phases +from eth2spec.test.context import spec_state_test, with_all_phases from eth2spec.test.helpers.state import ( next_epoch, next_slot @@ -37,7 +37,7 @@ def run_process_crosslinks(spec, state, valid=True): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_no_attestations(spec, state): yield from run_process_crosslinks(spec, state) @@ -46,7 +46,7 @@ def test_no_attestations(spec, state): assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_single_crosslink_update_from_current_epoch(spec, state): next_epoch(spec, state) @@ -67,7 +67,7 @@ def test_single_crosslink_update_from_current_epoch(spec, state): assert pre_crosslink != state.current_crosslinks[shard] -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_single_crosslink_update_from_previous_epoch(spec, state): next_epoch(spec, state) @@ -98,7 +98,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state): assert crosslink_deltas[1][index] == 0 -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_double_late_crosslink(spec, state): if spec.get_epoch_committee_count(state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py index daa52dba9..e6679f844 100644 --- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py +++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py @@ -1,7 +1,7 @@ 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.state import next_epoch -from eth2spec.test.context import spec_state_test, with_phases +from eth2spec.test.context import spec_state_test, with_all_phases def run_process_registry_updates(spec, state, valid=True): @@ -31,7 +31,7 @@ def run_process_registry_updates(spec, state, valid=True): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_activation(spec, state): index = 0 @@ -56,7 +56,7 @@ def test_activation(spec, state): ) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_ejection(spec, state): index = 0 diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py index f028217c6..110231d77 100644 --- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py +++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py @@ -1,7 +1,7 @@ from eth2spec.test.helpers.custody import get_valid_early_derived_secret_reveal from eth2spec.test.helpers.block import apply_empty_block from eth2spec.test.helpers.state import next_epoch, get_balance -from eth2spec.test.context import with_phases, spec_state_test, expect_assertion_error +from eth2spec.test.context import with_all_phases_except, spec_state_test, expect_assertion_error def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, valid=True): @@ -35,7 +35,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v yield 'post', state -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_success(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state) @@ -43,7 +43,7 @@ def test_success(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_reveal_from_current_epoch(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state)) @@ -51,7 +51,7 @@ def test_reveal_from_current_epoch(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_reveal_from_past_epoch(spec, state): next_epoch(spec, state) @@ -61,7 +61,7 @@ def test_reveal_from_past_epoch(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_reveal_with_custody_padding(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( @@ -72,7 +72,7 @@ def test_reveal_with_custody_padding(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_reveal_with_custody_padding_minus_one(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( @@ -83,7 +83,7 @@ def test_reveal_with_custody_padding_minus_one(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, True) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_double_reveal(spec, state): randao_key_reveal1 = get_valid_early_derived_secret_reveal( @@ -107,7 +107,7 @@ def test_double_reveal(spec, state): yield 'post', post_state -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_revealer_is_slashed(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state)) @@ -116,7 +116,7 @@ def test_revealer_is_slashed(spec, state): yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False) -@with_phases(['phase1']) +@with_all_phases_except(['phase0']) @spec_state_test def test_far_future_epoch(spec, state): randao_key_reveal = get_valid_early_derived_secret_reveal( diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py index c08dd83cd..587c37742 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py @@ -13,10 +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.deposits import prepare_state_and_deposit -from eth2spec.test.context import spec_state_test, never_bls, with_phases +from eth2spec.test.context import spec_state_test, never_bls, with_all_phases -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_empty_block_transition(spec, state): @@ -35,7 +35,7 @@ def test_empty_block_transition(spec, state): assert spec.get_block_root_at_slot(state, pre_slot) == block.parent_root -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_skipped_slots(spec, state): @@ -55,7 +55,7 @@ def test_skipped_slots(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_empty_epoch_transition(spec, state): pre_slot = state.slot @@ -74,7 +74,7 @@ def test_empty_epoch_transition(spec, state): assert spec.get_block_root_at_slot(state, slot) == block.parent_root -# @with_phases(['phase0', 'phase1']) +# @with_all_phases # @spec_state_test # def test_empty_epoch_transition_not_finalizing(spec, state): # # copy for later balance lookups. @@ -95,7 +95,7 @@ def test_empty_epoch_transition(spec, state): # assert get_balance(state, index) < get_balance(pre_state, index) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_proposer_slashing(spec, state): # copy for later balance lookups. @@ -127,7 +127,7 @@ def test_proposer_slashing(spec, state): assert get_balance(state, validator_index) < get_balance(pre_state, validator_index) -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_attester_slashing(spec, state): # copy for later balance lookups. @@ -169,7 +169,7 @@ def test_attester_slashing(spec, state): # TODO update functions below to be like above, i.e. with @spec_state_test and yielding data to put into the test vector -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_deposit_in_block(spec, state): initial_registry_len = len(state.validator_registry) @@ -196,7 +196,7 @@ def test_deposit_in_block(spec, state): assert state.validator_registry[validator_index].pubkey == pubkeys[validator_index] -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_deposit_top_up(spec, state): validator_index = 0 @@ -223,7 +223,7 @@ def test_deposit_top_up(spec, state): assert get_balance(state, validator_index) == validator_pre_balance + amount -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_attestation(spec, state): state.slot = spec.SLOTS_PER_EPOCH @@ -257,7 +257,7 @@ def test_attestation(spec, state): assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_voluntary_exit(spec, state): validator_index = spec.get_active_validator_indices( @@ -303,7 +303,7 @@ def test_voluntary_exit(spec, state): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_transfer(spec, state): # overwrite default 0 to test @@ -337,7 +337,7 @@ def test_transfer(spec, state): assert recipient_balance == pre_transfer_recipient_balance + amount -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_balance_driven_status_transitions(spec, state): current_epoch = spec.get_current_epoch(state) @@ -362,7 +362,7 @@ def test_balance_driven_status_transitions(spec, state): assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_historical_batch(spec, state): state.slot += spec.SLOTS_PER_HISTORICAL_ROOT - (state.slot % spec.SLOTS_PER_HISTORICAL_ROOT) - 1 @@ -381,7 +381,7 @@ def test_historical_batch(spec, state): assert len(state.historical_roots) == pre_historical_roots_len + 1 -# @with_phases(['phase0', 'phase1']) +# @with_all_phases # @spec_state_test # def test_eth1_data_votes(spec, state): # yield 'pre', state diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_slots.py b/test_libs/pyspec/eth2spec/test/sanity/test_slots.py index feddd65be..6ef6be4d3 100644 --- a/test_libs/pyspec/eth2spec/test/sanity/test_slots.py +++ b/test_libs/pyspec/eth2spec/test/sanity/test_slots.py @@ -1,8 +1,8 @@ from eth2spec.test.helpers.state import get_state_root -from eth2spec.test.context import spec_state_test, with_phases +from eth2spec.test.context import spec_state_test, with_all_phases -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_slots_1(spec, state): pre_slot = state.slot @@ -18,7 +18,7 @@ def test_slots_1(spec, state): assert get_state_root(spec, state, pre_slot) == pre_root -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_slots_2(spec, state): yield 'pre', state @@ -28,7 +28,7 @@ def test_slots_2(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_empty_epoch(spec, state): yield 'pre', state @@ -38,7 +38,7 @@ def test_empty_epoch(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_double_empty_epoch(spec, state): yield 'pre', state @@ -48,7 +48,7 @@ def test_double_empty_epoch(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @spec_state_test def test_over_epoch_boundary(spec, state): spec.process_slots(state, state.slot + (spec.SLOTS_PER_EPOCH // 2)) diff --git a/test_libs/pyspec/eth2spec/test/test_finality.py b/test_libs/pyspec/eth2spec/test/test_finality.py index 2d2e01432..801e8b4fd 100644 --- a/test_libs/pyspec/eth2spec/test/test_finality.py +++ b/test_libs/pyspec/eth2spec/test/test_finality.py @@ -1,7 +1,7 @@ from copy import deepcopy from typing import List -from eth2spec.test.context import spec_state_test, never_bls, with_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.block import build_empty_block_for_next_slot, apply_empty_block from eth2spec.test.helpers.attestations import get_valid_attestation @@ -60,7 +60,7 @@ def next_epoch_with_attestations(spec, return state, blocks, post_state -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_finality_rule_4(spec, state): @@ -89,7 +89,7 @@ def test_finality_rule_4(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_finality_rule_1(spec, state): @@ -120,7 +120,7 @@ def test_finality_rule_1(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_finality_rule_2(spec, state): @@ -153,7 +153,7 @@ def test_finality_rule_2(spec, state): yield 'post', state -@with_phases(['phase0', 'phase1']) +@with_all_phases @never_bls @spec_state_test def test_finality_rule_3(spec, state):