Skip to content
This repository has been archived by the owner on Jul 1, 2021. It is now read-only.

Commit

Permalink
Add state-fixtures/test_minimal_state.py
Browse files Browse the repository at this point in the history
  • Loading branch information
hwwhww committed May 2, 2019
1 parent 6e8d938 commit 3115c1c
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 5 deletions.
2 changes: 2 additions & 0 deletions eth2/beacon/epoch_processing_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ def _filter_attestations_by_latest_crosslinks_and_shard(
shard: Shard) -> Iterable[PendingAttestationRecord]:
for attestation in attestations:
is_latest_crosslink_matched = attestation.data.previous_crosslink == latest_crosslink
# NOTE: v0.5.1 doesn't check is_shard_matched but it's fixed in v0.6.0
# We implemented ahead here.
is_shard_matched = attestation.data.shard == shard
if is_latest_crosslink_matched and is_shard_matched:
yield attestation
Expand Down
11 changes: 8 additions & 3 deletions eth2/beacon/state_machines/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class BaseBeaconStateMachine(Configurable, ABC):
@abstractmethod
def __init__(self,
chaindb: BaseBeaconChainDB,
block_root: Hash32) -> None:
block: BaseBeaconBlock,
state: BeaconState=None) -> None:
pass

@classmethod
Expand Down Expand Up @@ -87,9 +88,13 @@ def create_block_from_parent(parent_block: BaseBeaconBlock,
class BeaconStateMachine(BaseBeaconStateMachine):
def __init__(self,
chaindb: BaseBeaconChainDB,
block: BaseBeaconBlock) -> None:
block: BaseBeaconBlock,
state: BeaconState=None) -> None:
self.chaindb = chaindb
self.block = block
if state is not None:
self._state = state
else:
self.block = block

@property
def state(self) -> BeaconState:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
from eth2.beacon.typing import (
Bitfield,
Epoch,
Shard,
Slot,
ValidatorIndex,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def apply_state_transition(self,
else:
raise Exception(
f"Invariant: state.slot ({state.slot}) should be less "
"than block.slot ({block.slot}) so that state transition terminates"
f"than block.slot ({block.slot}) so that state transition terminates"
)
return state

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"pytest-cov==2.5.1",
"pytest-watch>=4.1.0,<5",
"pytest-xdist==1.18.1",
"pytest-mock==1.10.4",
# only needed for p2p
"pytest-asyncio-network-simulator==0.1.0a2;python_version>='3.6'",
],
Expand Down
138 changes: 138 additions & 0 deletions tests/eth2/beacon/state-fixtures/test_minimal_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import os
import yaml
import pytest

from py_ecc import bls
import ssz

from eth2.configs import (
Eth2Config,
)
from eth2.beacon.db.chain import BeaconChainDB
from eth2.beacon.tools.misc.ssz_vector import (
override_vector_lengths,
)
from eth2.beacon.types.states import BeaconState
from eth2.beacon.state_machines.forks.serenity.blocks import SerenityBeaconBlock
from eth2.beacon.state_machines.forks.serenity import (
SerenityStateMachine,
)

# Test files
ROOT_PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

BASE_FIXTURE_PATH = os.path.join(ROOT_PROJECT_DIR, '../../', 'eth2-fixtures', 'state')

FILE_NAMES = [
"sanity-check_small-config_32-vals.yaml",
"sanity-check_default-config_100-vals.yaml",
]

#
# Mock bls verification for these tests
#
bls = bls


def mock_bls_verify(message_hash, pubkey, signature, domain):
return True


def mock_bls_verify_multiple(pubkeys,
message_hashes,
signature,
domain):
return True


@pytest.fixture(autouse=True)
def mock_bls(mocker, request):
if 'noautofixt' in request.keywords:
return

mocker.patch('py_ecc.bls.verify', side_effect=mock_bls_verify)
mocker.patch('py_ecc.bls.verify_multiple', side_effect=mock_bls_verify_multiple)


def get_test_case(file_names):
all_test_cases = []
for file_name in file_names:
with open(BASE_FIXTURE_PATH + '/' + file_name, 'U') as f:
# TODO: `proof_of_possession` is used in v0.5.1 spec and will be renamed to `signature`
# Trinity renamed it ahead due to py-ssz signing_root requirements
new_text = f.read().replace('proof_of_possession', 'signature')
try:
data = yaml.load(new_text)
all_test_cases += data['test_cases']
except yaml.YAMLError as exc:
print(exc)
return all_test_cases


test_cases = get_test_case(FILE_NAMES)


@pytest.mark.parametrize("test_case", test_cases)
def test_state(base_db, test_case):
test_name = test_case['name']
if test_name == 'test_transfer':
print('skip')
else:
execute_state_transtion(test_case, base_db)


def generate_config_by_dict(dict_config):
dict_config['DEPOSIT_CONTRACT_ADDRESS'] = b'\x00' * 20
for key in list(dict_config):
if 'DOMAIN_' in key in key:
# DOMAIN is defined in SignatureDomain
dict_config.pop(key, None)
return Eth2Config(**dict_config)


def execute_state_transtion(test_case, base_db):
test_name = test_case['name']
dict_config = test_case['config']
verify_signatures = test_case['verify_signatures']
dict_initial_state = test_case['initial_state']
dict_blocks = test_case['blocks']
dict_expected_state = test_case['expected_state']

# TODO: make it case by case
assert verify_signatures is False

print(f"[{test_name}]")

# Set config
config = generate_config_by_dict(dict_config)

# Set Vector fields
override_vector_lengths(config)

# Set pre_state
pre_state = ssz.tools.from_formatted_dict(dict_initial_state, BeaconState)

# Set blocks
blocks = ()
for dict_block in dict_blocks:
block = ssz.tools.from_formatted_dict(dict_block, SerenityBeaconBlock)
blocks += (block,)

sm_class = SerenityStateMachine.configure(
__name__='SerenityStateMachineForTesting',
config=config,
)
chaindb = BeaconChainDB(base_db)

post_state = pre_state.copy()
for block in blocks:
sm = sm_class(chaindb, None, post_state)
post_state, _ = sm.import_block(block)

# Use dict diff, easier to see the diff
dict_post_state = ssz.tools.to_formatted_dict(post_state, BeaconState)

for key, value in dict_expected_state.items():
if isinstance(value, list):
value = tuple(value)
assert dict_post_state[key] == value

0 comments on commit 3115c1c

Please sign in to comment.