@@ -39,12 +39,13 @@ class BaseBeaconStateMachine(Configurable, ABC):
39
39
config = None # type: BeaconConfig
40
40
41
41
block = None # type: BaseBeaconBlock
42
- block_class = None # type: Type[BaseBeaconBlock]
43
42
43
+ block_class = None # type: Type[BaseBeaconBlock]
44
44
crystallized_state_class = None # type: Type[CrystallizedState]
45
-
46
45
active_state_class = None # type: Type[ActiveState]
47
46
47
+ # TODO: Add abstractmethods
48
+
48
49
49
50
class BeaconStateMachine (BaseBeaconStateMachine ):
50
51
"""
@@ -74,7 +75,7 @@ def logger(self):
74
75
@classmethod
75
76
def get_block_class (cls ) -> Type [BaseBeaconBlock ]:
76
77
"""
77
- Return the :class:`~eth.beacon.types.blocks.BeaconBlock` class that this
78
+ Returns the :class:`~eth.beacon.types.blocks.BeaconBlock` class that this
78
79
StateMachine uses for blocks.
79
80
"""
80
81
if cls .block_class is None :
@@ -83,25 +84,30 @@ def get_block_class(cls) -> Type[BaseBeaconBlock]:
83
84
return cls .block_class
84
85
85
86
@classmethod
86
- @functools .lru_cache (maxsize = 32 )
87
87
@to_tuple
88
- def get_prev_blocks_to_slot (cls ,
89
- last_block_hash : Hash32 ,
90
- chaindb : BaseBeaconChainDB ,
91
- depth : int ,
92
- start_slot : int ) -> Iterable [BaseBeaconBlock ]:
88
+ def get_prev_blocks (cls ,
89
+ last_block_hash : Hash32 ,
90
+ chaindb : BaseBeaconChainDB ,
91
+ searching_depth : int ,
92
+ target_slot_number : int ) -> Iterable [BaseBeaconBlock ]:
93
+ """
94
+ Returns the previous blocks.
95
+
96
+ Since the slot numbers might be not continuous. The searching depth is ``searching_depth``
97
+ and the target slot depth is ``target_slot_number``.
98
+ """
93
99
if last_block_hash == GENESIS_PARENT_HASH :
94
100
return
95
101
96
102
block = chaindb .get_block_by_hash (last_block_hash )
97
103
98
- for _ in range (depth ):
104
+ for _ in range (searching_depth ):
99
105
yield block
100
106
try :
101
107
block = chaindb .get_block_by_hash (block .parent_hash )
102
108
except (IndexError , BlockNotFound ):
103
109
break
104
- if block .slot_number < start_slot :
110
+ if block .slot_number < target_slot_number :
105
111
break
106
112
107
113
@property
@@ -127,7 +133,7 @@ def crystallized_state(self) -> CrystallizedState:
127
133
@classmethod
128
134
def get_crystallized_state_class (cls ) -> Type [CrystallizedState ]:
129
135
"""
130
- Return the :class:`~eth.beacon.types.crystallized_states.CrystallizedState` class that this
136
+ Returns the :class:`~eth.beacon.types.crystallized_states.CrystallizedState` class that this
131
137
StateMachine uses for crystallized_state.
132
138
"""
133
139
if cls .crystallized_state_class is None :
@@ -144,38 +150,44 @@ def active_state(self) -> ActiveState:
144
150
Returns latest active state.
145
151
146
152
It was backed up per cycle. The latest ActiveState could be reproduced by
147
- ``old_active_state `` and recent blocks.
153
+ ``backup_active_state `` and recent blocks.
148
154
149
155
NOTE: The following logic in beacon chain spec will be changed with the current spec.
150
156
"""
151
157
if self ._active_state is None :
152
158
# Reproduce ActiveState
153
- old_active_state_root = self .chaindb .get_active_state_root_by_crystallized (
159
+ backup_active_state_root = self .chaindb .get_active_state_root_by_crystallized (
154
160
self .crystallized_state .hash
155
161
)
156
- old_active_state = self .chaindb .get_active_state_by_root (old_active_state_root )
157
- old_active_state_slot = self .crystallized_state .last_state_recalc
158
-
159
- depth = self .config .CYCLE_LENGTH * 2
160
- blocks = self .get_prev_blocks_to_slot (
161
- self .parent_block .hash ,
162
- self .chaindb ,
163
- depth ,
164
- start_slot = old_active_state_slot
165
- )
166
- blocks = blocks [::- 1 ]
167
-
168
- self ._active_state = self .get_active_state_class ().from_old_active_state_and_blocks (
169
- old_active_state ,
170
- blocks ,
171
- )
162
+ backup_active_state = self .chaindb .get_active_state_by_root (backup_active_state_root )
163
+ backup_active_state_slot = self .crystallized_state .last_state_recalc
164
+
165
+ if backup_active_state_root == self .parent_block .active_state_root :
166
+ # The backup ActiveState matches current block.
167
+ self ._active_state = backup_active_state
168
+ else :
169
+ # Get recent blocks after last ActiveState backup.
170
+ searching_depth = self .config .CYCLE_LENGTH * 2
171
+ blocks = self .get_prev_blocks (
172
+ last_block_hash = self .parent_block .hash ,
173
+ chaindb = self .chaindb ,
174
+ searching_depth = searching_depth ,
175
+ target_slot_number = backup_active_state_slot
176
+ )
177
+ blocks = blocks [::- 1 ]
178
+
179
+ self ._active_state = self .get_active_state_class (
180
+ ).from_backup_active_state_and_blocks (
181
+ backup_active_state ,
182
+ blocks ,
183
+ )
172
184
173
185
return self ._active_state
174
186
175
187
@classmethod
176
188
def get_active_state_class (cls ) -> Type [ActiveState ]:
177
189
"""
178
- Return the :class:`~eth.beacon.types.active_states.ActiveState` class that this
190
+ Returns the :class:`~eth.beacon.types.active_states.ActiveState` class that this
179
191
StateMachine uses for crystallized_state.
180
192
"""
181
193
if cls .active_state_class is None :
0 commit comments