Skip to content

Commit 7ad4259

Browse files
authored
Merge pull request #1400 from hwwhww/cycle_transition2
Add `compute_cycle_transitions`
2 parents e4a203a + 082be9e commit 7ad4259

File tree

7 files changed

+156
-39
lines changed

7 files changed

+156
-39
lines changed

eth/beacon/state_machines/base.py

Lines changed: 104 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
to_tuple,
1616
)
1717

18-
1918
from eth.constants import (
2019
GENESIS_PARENT_HASH,
2120
)
@@ -44,7 +43,9 @@
4443
from eth.beacon.types.active_states import ActiveState
4544
from eth.beacon.types.attestation_records import AttestationRecord # noqa: F401
4645
from eth.beacon.types.blocks import BaseBeaconBlock
46+
from eth.beacon.types.crosslink_records import CrosslinkRecord # noqa: F401
4747
from eth.beacon.types.crystallized_states import CrystallizedState
48+
from eth.beacon.types.validator_records import ValidatorRecord # noqa: F401
4849
from eth.beacon.state_machines.configs import BeaconConfig # noqa: F401
4950

5051
from .validation import (
@@ -259,7 +260,6 @@ def import_block(
259260
self.active_state,
260261
block,
261262
self.chaindb,
262-
self.config,
263263
is_validating_signatures=True,
264264
)
265265

@@ -272,10 +272,17 @@ def import_block(
272272

273273
self.block = processing_block
274274
self._update_the_states(processed_crystallized_state, processed_active_state)
275+
275276
# TODO: persist states in BeaconChain if needed
276277

277278
return self.block, self.crystallized_state, self.active_state
278279

280+
def _update_the_states(self,
281+
crystallized_state: CrystallizedState,
282+
active_state: ActiveState) -> None:
283+
self._crytallized_state = crystallized_state
284+
self._active_state = active_state
285+
279286
#
280287
# Process block APIs
281288
#
@@ -286,7 +293,6 @@ def process_block(
286293
active_state: ActiveState,
287294
block: BaseBeaconBlock,
288295
chaindb: BaseBeaconChainDB,
289-
config: BeaconConfig,
290296
is_validating_signatures: bool=True
291297
) -> Tuple[BaseBeaconBlock, CrystallizedState, ActiveState]:
292298
"""
@@ -298,14 +304,14 @@ def process_block(
298304
active_state,
299305
block,
300306
chaindb,
301-
config.CYCLE_LENGTH,
302307
is_validating_signatures=is_validating_signatures,
303308
)
304309

305310
# Process per cycle state changes (CrystallizedState and ActiveState)
306311
processed_crystallized_state, processed_active_state = cls.compute_cycle_transitions(
307312
crystallized_state,
308313
processing_active_state,
314+
block,
309315
)
310316

311317
# Return the copy
@@ -318,12 +324,10 @@ def compute_per_block_transition(cls,
318324
active_state: ActiveState,
319325
block: BaseBeaconBlock,
320326
chaindb: BaseBeaconChainDB,
321-
cycle_length: int,
322327
is_validating_signatures: bool=True) -> ActiveState:
323328
"""
324329
Process ``block`` and return the new ActiveState.
325330
326-
327331
TODO: It doesn't match the latest spec.
328332
There will be more fields need to be updated in ActiveState.
329333
"""
@@ -340,11 +344,12 @@ def compute_per_block_transition(cls,
340344
crystallized_state,
341345
block,
342346
parent_block,
343-
cycle_length,
347+
cls.config.CYCLE_LENGTH,
344348
)
345349

346350
# TODO: to implement the RANDAO reveal validation.
347351
cls.validate_randao_reveal()
352+
348353
for attestation in block.attestations:
349354
validate_attestation(
350355
block,
@@ -353,7 +358,7 @@ def compute_per_block_transition(cls,
353358
recent_block_hashes,
354359
attestation,
355360
chaindb,
356-
cycle_length,
361+
cls.config.CYCLE_LENGTH,
357362
is_validating_signatures=is_validating_signatures,
358363
)
359364

@@ -368,33 +373,112 @@ def compute_per_block_transition(cls,
368373
def compute_cycle_transitions(
369374
cls,
370375
crystallized_state: CrystallizedState,
371-
active_state: ActiveState) -> Tuple[CrystallizedState, ActiveState]:
372-
# TODO: it's a stub
376+
active_state: ActiveState,
377+
block: BaseBeaconBlock) -> Tuple[CrystallizedState, ActiveState]:
378+
"""
379+
Compute the cycle transitions and return processed CrystallizedState and ActiveState.
380+
"""
381+
while block.slot_number >= crystallized_state.last_state_recalc + cls.config.CYCLE_LENGTH:
382+
crystallized_state, active_state = cls.compute_per_cycle_transition(
383+
crystallized_state,
384+
active_state,
385+
block,
386+
)
387+
388+
if cls.ready_for_dynasty_transition(crystallized_state, block):
389+
crystallized_state = cls.compute_dynasty_transition(
390+
crystallized_state,
391+
block,
392+
)
393+
394+
return crystallized_state, active_state
395+
396+
@classmethod
397+
def compute_per_cycle_transition(
398+
cls,
399+
crystallized_state: CrystallizedState,
400+
active_state: ActiveState,
401+
block: BaseBeaconBlock) -> Tuple[CrystallizedState, ActiveState]:
402+
"""
403+
Initialize a new cycle.
404+
"""
405+
# TODO: it's a STUB before we implement compute_per_cycle_transition
406+
crystallized_state = crystallized_state.copy(
407+
last_state_recalc=crystallized_state.last_state_recalc + cls.config.CYCLE_LENGTH
408+
)
409+
373410
return crystallized_state, active_state
374411

412+
#
413+
# Crosslinks
414+
#
415+
@classmethod
416+
def update_crosslinks(cls,
417+
crystallized_state: CrystallizedState,
418+
active_state: ActiveState,
419+
block: BaseBeaconBlock) -> Tuple['CrosslinkRecord', ...]:
420+
# TODO
421+
return ()
422+
423+
#
424+
# Rewards and penalties
425+
#
426+
@classmethod
427+
def apply_rewards_and_penalties(cls,
428+
crystallized_state: CrystallizedState,
429+
active_state: ActiveState,
430+
block: BaseBeaconBlock) -> Tuple['ValidatorRecord', ...]:
431+
"""
432+
Apply the rewards and penalties to the validators and return the updated ValidatorRecords.
433+
"""
434+
# TODO
435+
return ()
436+
437+
#
438+
# Dynasty
439+
#
440+
@classmethod
441+
def ready_for_dynasty_transition(cls,
442+
crystallized_state: CrystallizedState,
443+
block: BaseBeaconBlock) -> bool:
444+
"""
445+
Check if it's ready for dynasty transition.
446+
"""
447+
# TODO
448+
return False
449+
450+
@classmethod
451+
def compute_dynasty_transition(cls,
452+
crystallized_state: CrystallizedState,
453+
block: BaseBeaconBlock) -> CrystallizedState:
454+
"""
455+
Compute the dynasty transition.
456+
"""
457+
# TODO
458+
return crystallized_state
459+
375460
#
376461
#
377462
# Proposer APIs
378463
#
379464
#
465+
@classmethod
380466
def propose_block(
381-
self,
467+
cls,
382468
crystallized_state: CrystallizedState,
383469
active_state: ActiveState,
384470
block_proposal: 'BlockProposal',
385471
chaindb: BaseBeaconChainDB,
386-
config: BeaconConfig,
387472
private_key: int
388473
) -> Tuple[BaseBeaconBlock, CrystallizedState, ActiveState, 'AttestationRecord']:
389474
"""
390475
Propose the given block.
391476
"""
392-
block, post_crystallized_state, post_active_state = self.process_block(
477+
block, post_crystallized_state, post_active_state = cls.process_block(
393478
crystallized_state,
394479
active_state,
395480
block_proposal.block,
396481
chaindb,
397-
config,
398482
is_validating_signatures=False,
399483
)
400484

@@ -409,28 +493,21 @@ def propose_block(
409493
shard_block_hash=block_proposal.shard_block_hash,
410494
)
411495

412-
proposer_attestation = self.attest_proposed_block(
496+
proposer_attestation = cls.attest_proposed_block(
413497
post_crystallized_state,
414498
post_active_state,
415499
filled_block_proposal,
416500
chaindb,
417-
config.CYCLE_LENGTH,
418501
private_key,
419502
)
420503
return post_block, post_crystallized_state, post_active_state, proposer_attestation
421504

422-
def _update_the_states(self,
423-
crystallized_state: CrystallizedState,
424-
active_state: ActiveState) -> None:
425-
self._crytallized_state = crystallized_state
426-
self._active_state = active_state
427-
428-
def attest_proposed_block(self,
505+
@classmethod
506+
def attest_proposed_block(cls,
429507
post_crystallized_state: CrystallizedState,
430508
post_active_state: ActiveState,
431509
block_proposal: 'BlockProposal',
432510
chaindb: BaseBeaconChainDB,
433-
cycle_length: int,
434511
private_key: int) -> 'AttestationRecord':
435512
"""
436513
Return the initial attestation by the block proposer.
@@ -440,7 +517,7 @@ def attest_proposed_block(self,
440517
block_committees_info = get_block_committees_info(
441518
block_proposal.block,
442519
post_crystallized_state,
443-
cycle_length,
520+
cls.config.CYCLE_LENGTH,
444521
)
445522
# Vote
446523
attester_bitfield = set_voted(
@@ -456,7 +533,7 @@ def attest_proposed_block(self,
456533
parent_hashes = get_hashes_to_sign(
457534
post_active_state.recent_block_hashes,
458535
block_proposal.block,
459-
cycle_length,
536+
cls.config.CYCLE_LENGTH,
460537
)
461538

462539
message = create_signing_message(
@@ -471,7 +548,7 @@ def attest_proposed_block(self,
471548
private_key,
472549
)
473550

474-
return self.get_attestation_record_class()(
551+
return cls.get_attestation_record_class()(
475552
slot=block_proposal.block.slot_number,
476553
shard_id=block_proposal.shard_id,
477554
oblique_parent_hashes=(),

eth/beacon/types/crystallized_states.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def active_validator_indices(self) -> Tuple[int]:
106106
)
107107

108108
@property
109-
def total_deposits(self) -> int:
109+
def total_balance(self) -> int:
110110
return sum(
111111
self.validators[index].balance
112112
for index in self.active_validator_indices

tests/beacon/state_machines/test_block_validation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ def attestation_validation_fixture(fixture_sm_class,
7070
active_state=sm.active_state,
7171
block_proposal=block_proposal,
7272
chaindb=sm.chaindb,
73-
config=sm.config,
7473
private_key=private_key,
7574
)
7675
)

tests/beacon/state_machines/test_proposer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ def test_propose_block(fixture_sm_class,
6262
active_state=sm.active_state,
6363
block_proposal=block_proposal,
6464
chaindb=sm.chaindb,
65-
config=sm.config,
6665
private_key=private_key,
6766
)
6867
)
@@ -119,7 +118,6 @@ def test_propose_block(fixture_sm_class,
119118
active_state=sm.active_state,
120119
block_proposal=block_proposal,
121120
chaindb=sm.chaindb,
122-
config=sm.config,
123121
private_key=private_key,
124122
)
125123
)

tests/beacon/state_machines/test_state_machines.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,46 @@ def test_import_block_one(fixture_sm_class,
9595
[ZERO_HASH32] * (sm.config.CYCLE_LENGTH * 2 - 1) + [genesis_block.hash]
9696
)
9797
assert active_state.recent_block_hashes == expect
98+
99+
100+
@pytest.mark.parametrize(
101+
(
102+
'num_validators,cycle_length,min_committee_size,shard_count,'
103+
'block_slot,'
104+
'prev_last_state_recalculation_slot,'
105+
'post_last_state_recalculation_slot'
106+
),
107+
[
108+
(1000, 20, 10, 100, 1, 0, 0), # no cycle transition
109+
(1000, 20, 10, 100, 20, 0, 20), # transition: 0 + cycle_length
110+
(1000, 20, 10, 100, 60, 5, 45), # transition: 5 + 2 * cycle_length
111+
(1000, 20, 10, 100, 61, 45, 45), # no cycle transition
112+
]
113+
)
114+
def test_compute_cycle_transitions(fixture_sm_class,
115+
initial_chaindb,
116+
genesis_block,
117+
genesis_crystallized_state,
118+
genesis_active_state,
119+
block_slot,
120+
prev_last_state_recalculation_slot,
121+
post_last_state_recalculation_slot):
122+
chaindb = initial_chaindb
123+
124+
block_1_shell = genesis_block.copy(
125+
parent_hash=genesis_block.hash,
126+
slot_number=genesis_block.slot_number + 1,
127+
)
128+
129+
sm = fixture_sm_class(chaindb, block_1_shell)
130+
131+
post_crystallized_state, _ = sm.compute_cycle_transitions(
132+
genesis_crystallized_state.copy(
133+
last_state_recalc=prev_last_state_recalculation_slot,
134+
),
135+
genesis_active_state,
136+
genesis_block.copy(
137+
slot_number=block_slot,
138+
)
139+
)
140+
assert post_crystallized_state.last_state_recalc == post_last_state_recalculation_slot

tests/beacon/test_genesis_helpers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_get_genesis_crystallized_state(genesis_validators,
2828
shard_count,
2929
)
3030
len_shard_and_committee_for_slots = cycle_length * 2
31-
total_deposits = deposit_size * len(genesis_validators)
31+
total_balance = deposit_size * len(genesis_validators)
3232

3333
assert crystallized_state.validators == genesis_validators
3434
assert crystallized_state.last_state_recalc == 0
@@ -43,7 +43,7 @@ def test_get_genesis_crystallized_state(genesis_validators,
4343
assert crosslink.hash == ZERO_HASH32
4444
assert crosslink.slot == 0
4545
assert crosslink.dynasty == 0
46-
assert crystallized_state.total_deposits == total_deposits
46+
assert crystallized_state.total_balance == total_balance
4747
assert crystallized_state.dynasty_seed == init_shuffling_seed
4848
assert crystallized_state.dynasty_start == 0
4949

0 commit comments

Comments
 (0)