diff --git a/eth2/beacon/chains/base.py b/eth2/beacon/chains/base.py index d09f30edf6..e7017ee84a 100644 --- a/eth2/beacon/chains/base.py +++ b/eth2/beacon/chains/base.py @@ -1,38 +1,38 @@ from abc import ( ABC, - abstractmethod + abstractmethod, ) +import logging from typing import ( + TYPE_CHECKING, Tuple, Type, ) -import logging - -from eth_typing import ( - Hash32, +from eth._utils.datatypes import ( + Configurable, ) -from eth_utils import ( - encode_hex, - ValidationError, +from eth.db.backends.base import ( + BaseAtomicDB, ) - -from eth.db.backends.base import BaseAtomicDB from eth.exceptions import ( BlockNotFound, ) from eth.validation import ( validate_word, ) - -from eth._utils.datatypes import ( - Configurable, +from eth_typing import ( + Hash32, +) +from eth_utils import ( + ValidationError, + encode_hex, ) + from eth2._utils.ssz import ( validate_imported_block_unchanged, ) - -from eth2.beacon.db.chain import ( # noqa: F401 +from eth2.beacon.db.chain import ( BaseBeaconChainDB, BeaconChainDB, ) @@ -40,11 +40,12 @@ BlockClassError, StateMachineNotFound, ) -from eth2.beacon.state_machines.base import BaseBeaconStateMachine # noqa: F401 from eth2.beacon.types.blocks import ( BaseBeaconBlock, ) -from eth2.beacon.types.states import BeaconState +from eth2.beacon.types.states import ( + BeaconState, +) from eth2.beacon.typing import ( FromBlockParams, Slot, @@ -53,6 +54,11 @@ validate_slot, ) +if TYPE_CHECKING: + from eth2.beacon.state_machines.base import ( # noqa: F401 + BaseBeaconStateMachine, + ) + class BaseBeaconChain(Configurable, ABC): """ @@ -60,7 +66,7 @@ class BaseBeaconChain(Configurable, ABC): """ chaindb = None # type: BaseBeaconChainDB chaindb_class = None # type: Type[BaseBeaconChainDB] - sm_configuration = None # type: Tuple[Tuple[int, Type[BaseBeaconStateMachine]], ...] + sm_configuration = None # type: Tuple[Tuple[Slot, Type[BaseBeaconStateMachine]], ...] chain_id = None # type: int # diff --git a/eth2/beacon/chains/testnet/__init__.py b/eth2/beacon/chains/testnet/__init__.py new file mode 100644 index 0000000000..53c51a611d --- /dev/null +++ b/eth2/beacon/chains/testnet/__init__.py @@ -0,0 +1,42 @@ +from typing import ( + TYPE_CHECKING, +) +from eth2.beacon.chains.base import ( + BeaconChain, +) +from eth2.beacon.state_machines.forks.xiao_long_bao import ( + XiaoLongBaoStateMachine, +) +from eth2.beacon.state_machines.forks.serenity.configs import ( + SERENITY_CONFIG, +) +from .constants import ( + TESTNET_CHAIN_ID, +) + +if TYPE_CHECKING: + from eth2.beacon.typing import ( # noqa: F401 + Slot, + ) + from eth2.beacon.state_machines.base import ( # noqa: F401 + BaseBeaconStateMachine, + ) + from typing import ( # noqa: F401 + Tuple, + Type, + ) + + +TESTNET_SM_CONFIGURATION = ( + # FIXME: Shouldn't access GENESIS_SLOT from a particular state machine configs. + (SERENITY_CONFIG.GENESIS_SLOT, XiaoLongBaoStateMachine), +) # type: Tuple[Tuple[Slot, Type[BaseBeaconStateMachine]], ...] + + +class BaseTestnetChain: + sm_configuration = TESTNET_SM_CONFIGURATION + chain_id = TESTNET_CHAIN_ID + + +class TestnetChain(BaseTestnetChain, BeaconChain): + pass diff --git a/eth2/beacon/chains/testnet/constants.py b/eth2/beacon/chains/testnet/constants.py new file mode 100644 index 0000000000..ad449a21db --- /dev/null +++ b/eth2/beacon/chains/testnet/constants.py @@ -0,0 +1,3 @@ + + +TESTNET_CHAIN_ID = 5566 diff --git a/eth2/beacon/state_machines/forks/xiao_long_bao/__init__.py b/eth2/beacon/state_machines/forks/xiao_long_bao/__init__.py new file mode 100644 index 0000000000..b66262c6a3 --- /dev/null +++ b/eth2/beacon/state_machines/forks/xiao_long_bao/__init__.py @@ -0,0 +1,40 @@ +from eth2.beacon.state_machines.base import ( + BeaconStateMachine, +) +from eth2.beacon.state_machines.forks.serenity.blocks import ( + SerenityBeaconBlock, + create_serenity_block_from_parent, +) +from eth2.beacon.state_machines.forks.serenity.state_transitions import ( + SerenityStateTransition, +) +from eth2.beacon.state_machines.forks.serenity.states import ( + SerenityBeaconState, +) +from eth2.beacon.types.blocks import ( + BaseBeaconBlock, +) +from eth2.beacon.typing import ( + FromBlockParams, +) + +from .configs import ( + XIAO_LONG_BAO_CONFIG, +) + + +class XiaoLongBaoStateMachine(BeaconStateMachine): + # fork name + fork = 'xiao_long_bao' + + # classes + block_class = SerenityBeaconBlock + state_class = SerenityBeaconState + state_transition_class = SerenityStateTransition + config = XIAO_LONG_BAO_CONFIG + + # methods + @staticmethod + def create_block_from_parent(parent_block: BaseBeaconBlock, + block_params: FromBlockParams) -> BaseBeaconBlock: + return create_serenity_block_from_parent(parent_block, block_params) diff --git a/eth2/beacon/state_machines/forks/xiao_long_bao/configs.py b/eth2/beacon/state_machines/forks/xiao_long_bao/configs.py new file mode 100644 index 0000000000..c221d668f0 --- /dev/null +++ b/eth2/beacon/state_machines/forks/xiao_long_bao/configs.py @@ -0,0 +1,17 @@ +from eth2.beacon.helpers import ( + slot_to_epoch, +) +from eth2.beacon.state_machines.forks.serenity.configs import ( + SERENITY_CONFIG, +) + + +SLOTS_PER_EPOCH = 4 + +XIAO_LONG_BAO_CONFIG = SERENITY_CONFIG._replace( + SLOTS_PER_EPOCH=SLOTS_PER_EPOCH, + GENESIS_EPOCH=slot_to_epoch(SERENITY_CONFIG.GENESIS_SLOT, SLOTS_PER_EPOCH), + TARGET_COMMITTEE_SIZE=2, + SHARD_COUNT=2, + MIN_ATTESTATION_INCLUSION_DELAY=2, +) diff --git a/tests/core/p2p-proto/bcc/helpers.py b/tests/core/p2p-proto/bcc/helpers.py index 16fee14bb1..a566f78d03 100644 --- a/tests/core/p2p-proto/bcc/helpers.py +++ b/tests/core/p2p-proto/bcc/helpers.py @@ -54,6 +54,7 @@ def __init__(self, db: BaseAtomicDB) -> None: coro_get_canonical_block_by_slot = async_passthrough('get_canonical_block_by_slot') coro_get_canonical_block_root_by_slot = async_passthrough('get_canonical_block_root_by_slot') coro_get_canonical_head = async_passthrough('get_canonical_head') + coro_get_canonical_head_root = async_passthrough('get_canonical_head_root') coro_get_finalized_head = async_passthrough('get_finalized_head') coro_get_block_by_root = async_passthrough('get_block_by_root') coro_get_score = async_passthrough('get_score') diff --git a/tests/eth2/beacon/chains/test_chain.py b/tests/eth2/beacon/chains/test_beacon_chain.py similarity index 100% rename from tests/eth2/beacon/chains/test_chain.py rename to tests/eth2/beacon/chains/test_beacon_chain.py diff --git a/tests/eth2/beacon/chains/test_chains.py b/tests/eth2/beacon/chains/test_chains.py new file mode 100644 index 0000000000..394fb52249 --- /dev/null +++ b/tests/eth2/beacon/chains/test_chains.py @@ -0,0 +1,13 @@ +import pytest +from eth2.beacon.chains.testnet import TestnetChain + + +@pytest.mark.parametrize( + "chain_klass", + ( + TestnetChain, + ) +) +def test_chain_class_well_defined(chain_klass): + chain = chain_klass(None) + assert chain.sm_configuration is not () and chain.sm_configuration is not None diff --git a/tests/eth2/beacon/state_machines/forks/test_fork_classes.py b/tests/eth2/beacon/state_machines/forks/test_fork_classes.py new file mode 100644 index 0000000000..e583057d1a --- /dev/null +++ b/tests/eth2/beacon/state_machines/forks/test_fork_classes.py @@ -0,0 +1,20 @@ +import pytest + +from eth2.beacon.state_machines.forks.serenity import ( + SerenityStateMachine, +) +from eth2.beacon.state_machines.forks.xiao_long_bao import ( + XiaoLongBaoStateMachine, +) + + +@pytest.mark.parametrize( + "sm_klass", + ( + SerenityStateMachine, + XiaoLongBaoStateMachine, + ) +) +def test_sm_class_well_defined(sm_klass): + state_machine = sm_klass(chaindb=None, block=None) + assert state_machine.get_block_class() diff --git a/trinity/db/beacon/chain.py b/trinity/db/beacon/chain.py index 550dc35b45..4f7e029247 100644 --- a/trinity/db/beacon/chain.py +++ b/trinity/db/beacon/chain.py @@ -63,6 +63,10 @@ async def coro_get_canonical_block_root_by_slot(self, slot: int) -> Hash32: async def coro_get_canonical_head(self, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock: pass + @abstractmethod + async def coro_get_canonical_head_root(self)-> Hash32: + pass + @abstractmethod async def coro_get_finalized_head(self, block_class: Type[BaseBeaconBlock]) -> BaseBeaconBlock: pass @@ -124,6 +128,7 @@ class AsyncBeaconChainDBPreProxy(BaseAsyncBeaconChainDB): coro_get_canonical_block_by_slot = async_method('get_canonical_block_by_slot') coro_get_canonical_block_root_by_slot = async_method('get_canonical_block_root_by_slot') coro_get_canonical_head = async_method('get_canonical_head') + coro_get_canonical_head_root = async_method('get_canonical_head_root') coro_get_finalized_head = async_method('get_finalized_head') coro_get_block_by_root = async_method('get_block_by_root') coro_get_score = async_method('get_score')