Skip to content

Commit a8ab3ec

Browse files
authored
Merge pull request #1633 from hwwhww/sm_stub
`StateMachine` and `StateTransition` layout
2 parents 629a4e4 + 2225100 commit a8ab3ec

File tree

12 files changed

+353
-7
lines changed

12 files changed

+353
-7
lines changed

eth/beacon/state_machines/base.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from abc import (
2+
ABC,
3+
abstractmethod,
4+
)
5+
from typing import (
6+
Tuple,
7+
Type,
8+
)
9+
10+
from eth.utils.datatypes import (
11+
Configurable,
12+
)
13+
14+
from eth.beacon.db.chain import BaseBeaconChainDB
15+
from eth.beacon.types.blocks import BaseBeaconBlock
16+
from eth.beacon.types.states import BeaconState
17+
18+
19+
from .state_transitions import (
20+
BaseStateTransition,
21+
)
22+
from .configs import ( # noqa: F401
23+
BeaconConfig,
24+
)
25+
26+
27+
class BaseBeaconStateMachine(Configurable, ABC):
28+
fork = None # type: str
29+
chaindb = None # type: BaseBeaconChainDB
30+
config = None # type: BeaconConfig
31+
32+
block = None # type: BaseBeaconBlock
33+
state = None # type: BeaconState
34+
35+
block_class = None # type: Type[BaseBeaconBlock]
36+
state_class = None # type: Type[BeaconState]
37+
state_transition_class = None # type: Type[BaseStateTransition]
38+
39+
@classmethod
40+
@abstractmethod
41+
def get_block_class(cls) -> Type[BaseBeaconBlock]:
42+
pass
43+
44+
@classmethod
45+
@abstractmethod
46+
def get_state_class(cls) -> Type[BeaconState]:
47+
pass
48+
49+
@classmethod
50+
@abstractmethod
51+
def get_state_transiton_class(cls) -> Type[BaseStateTransition]:
52+
pass
53+
54+
@property
55+
@abstractmethod
56+
def state_transition(self) -> BaseStateTransition:
57+
pass
58+
59+
#
60+
# Import block API
61+
#
62+
@abstractmethod
63+
def import_block(self, block: BaseBeaconBlock) -> Tuple[BeaconState, BaseBeaconBlock]:
64+
pass
65+
66+
67+
class BeaconStateMachine(BaseBeaconStateMachine):
68+
def __init__(self,
69+
chaindb: BaseBeaconChainDB,
70+
block: BaseBeaconBlock,
71+
state: BeaconState) -> None:
72+
# TODO: get state from DB, now it's just a stub!
73+
self.state = state
74+
75+
@classmethod
76+
def get_block_class(cls) -> Type[BaseBeaconBlock]:
77+
"""
78+
Return the :class:`~eth.beacon.types.blocks.BeaconBlock` class that this
79+
StateMachine uses for blocks.
80+
"""
81+
if cls.block_class is None:
82+
raise AttributeError("No `block_class` has been set for this StateMachine")
83+
else:
84+
return cls.block_class
85+
86+
@classmethod
87+
def get_state_class(cls) -> Type[BeaconState]:
88+
"""
89+
Return the :class:`~eth.beacon.types.states.BeaconState` class that this
90+
StateMachine uses for BeaconState.
91+
"""
92+
if cls.state_class is None:
93+
raise AttributeError("No `state_class` has been set for this StateMachine")
94+
else:
95+
return cls.state_class
96+
97+
@classmethod
98+
def get_state_transiton_class(cls) -> Type[BaseStateTransition]:
99+
"""
100+
Return the :class:`~eth.beacon.state_machines.state_transitions.BaseStateTransition`
101+
class that this StateTransition uses for StateTransition.
102+
"""
103+
if cls.state_transition_class is None:
104+
raise AttributeError("No `state_transition_class` has been set for this StateMachine")
105+
else:
106+
return cls.state_transition_class
107+
108+
@property
109+
def state_transition(self) -> BaseStateTransition:
110+
return self.get_state_transiton_class()(self.config)
111+
112+
#
113+
# Import block API
114+
#
115+
def import_block(self, block: BaseBeaconBlock) -> Tuple[BeaconState, BaseBeaconBlock]:
116+
state = self.state_transition.apply_state_transition(
117+
self.state,
118+
block,
119+
)
120+
# TODO: Validate state roots
121+
# TODO: Update self.state
122+
# TODO: persist states in BeaconChain
123+
return state, block

eth/beacon/state_machines/configs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
('TARGET_COMMITTEE_SIZE', int),
1616
('EJECTION_BALANCE', int),
1717
('MAX_BALANCE_CHURN_QUOTIENT', int),
18-
('GWEI_PER_ETH', int),
1918
('BEACON_CHAIN_SHARD_NUMBER', int),
2019
('BLS_WITHDRAWAL_PREFIX_BYTE', bytes),
2120
('MAX_CASPER_VOTES', int),
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from typing import Type # noqa: F401
2+
3+
from eth.beacon.types.blocks import BaseBeaconBlock # noqa: F401
4+
from eth.beacon.types.states import BeaconState # noqa: F401
5+
6+
from eth.beacon.state_machines.base import BeaconStateMachine
7+
from eth.beacon.state_machines.state_transitions import BaseStateTransition # noqa: F401
8+
9+
from .blocks import SerenityBeaconBlock
10+
from .states import SerenityBeaconState
11+
from .state_transitions import SerenityStateTransition
12+
from .configs import SERENITY_CONFIG
13+
14+
15+
class SerenityStateMachine(BeaconStateMachine):
16+
# fork name
17+
fork = 'serenity' # type: str
18+
19+
# classes
20+
block_class = SerenityBeaconBlock # type: Type[BaseBeaconBlock]
21+
state_class = SerenityBeaconState # type: Type[BeaconState]
22+
state_transition_class = SerenityStateTransition # type: Type[BaseStateTransition]
23+
config = SERENITY_CONFIG
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from eth.beacon.types.blocks import BaseBeaconBlock
2+
3+
4+
class SerenityBeaconBlock(BaseBeaconBlock):
5+
pass

eth/beacon/state_machines/forks/serenity/configs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
TARGET_COMMITTEE_SIZE=2**8, # (= 256) validators
1111
EJECTION_BALANCE=2**4, # (= 16) ETH
1212
MAX_BALANCE_CHURN_QUOTIENT=2**5, # (= 32)
13-
GWEI_PER_ETH=10**9, # Gwei/ETH
1413
BEACON_CHAIN_SHARD_NUMBER=2**64 - 1,
1514
BLS_WITHDRAWAL_PREFIX_BYTE=b'\x00',
1615
MAX_CASPER_VOTES=2**10, # (= 1,024) votes
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from eth.beacon.types.blocks import BaseBeaconBlock
2+
from eth.beacon.types.states import BeaconState
3+
from eth.beacon.state_machines.configs import BeaconConfig
4+
5+
6+
def process_attestations(state: BeaconState,
7+
block: BaseBeaconBlock,
8+
config: BeaconConfig) -> BeaconState:
9+
# TODO
10+
# It's just for demo!!!
11+
state = state.copy(
12+
slot=config.ZERO_BALANCE_VALIDATOR_TTL,
13+
)
14+
return state
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from eth.beacon.types.blocks import BaseBeaconBlock
2+
from eth.beacon.types.states import BeaconState
3+
4+
from eth.beacon.state_machines.configs import BeaconConfig
5+
from eth.beacon.state_machines.state_transitions import BaseStateTransition
6+
7+
from .operations import (
8+
process_attestations,
9+
)
10+
11+
12+
class SerenityStateTransition(BaseStateTransition):
13+
config = None
14+
15+
def __init__(self, config: BeaconConfig):
16+
self.config = config
17+
18+
def apply_state_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
19+
state = self.per_slot_transition(state, block)
20+
state = self.per_block_transition(state, block)
21+
state = self.per_epoch_transition(state, block)
22+
23+
return state
24+
25+
def per_slot_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
26+
# TODO
27+
return state
28+
29+
def per_block_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
30+
# TODO
31+
state = process_attestations(state, block, self.config)
32+
return state
33+
34+
def per_epoch_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
35+
# TODO
36+
return state
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from eth.beacon.types.states import BeaconState
2+
3+
4+
class SerenityBeaconState(BeaconState):
5+
pass
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from abc import (
2+
ABC,
3+
abstractmethod,
4+
)
5+
6+
from eth.utils.datatypes import (
7+
Configurable,
8+
)
9+
10+
from eth.beacon.types.blocks import BaseBeaconBlock
11+
from eth.beacon.types.states import BeaconState
12+
13+
from eth.beacon.state_machines.configs import BeaconConfig
14+
15+
16+
class BaseStateTransition(Configurable, ABC):
17+
config = None
18+
19+
def __init__(self, config: BeaconConfig):
20+
self.config = config
21+
22+
@abstractmethod
23+
def apply_state_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
24+
pass
25+
26+
@abstractmethod
27+
def per_slot_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
28+
pass
29+
30+
@abstractmethod
31+
def per_block_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
32+
pass
33+
34+
@abstractmethod
35+
def per_epoch_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
36+
pass

tests/beacon/conftest.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,6 @@ def max_balance_churn_quotient():
350350
return SERENITY_CONFIG.MAX_BALANCE_CHURN_QUOTIENT
351351

352352

353-
@pytest.fixture
354-
def gwei_per_eth():
355-
return SERENITY_CONFIG.GWEI_PER_ETH
356-
357-
358353
@pytest.fixture
359354
def beacon_chain_shard_number():
360355
return SERENITY_CONFIG.BEACON_CHAIN_SHARD_NUMBER
@@ -395,6 +390,16 @@ def max_deposit():
395390
return SERENITY_CONFIG.MAX_DEPOSIT
396391

397392

393+
@pytest.fixture
394+
def initial_fork_version():
395+
return SERENITY_CONFIG.INITIAL_FORK_VERSION
396+
397+
398+
@pytest.fixture
399+
def initial_slot_number():
400+
return SERENITY_CONFIG.INITIAL_SLOT_NUMBER
401+
402+
398403
@pytest.fixture
399404
def slot_duration():
400405
return SERENITY_CONFIG.SLOT_DURATION

0 commit comments

Comments
 (0)