Skip to content

Commit 000333a

Browse files
authored
Merge pull request #1695 from hwwhww/fix_get_block_root
Sync `get_block_root` and `get_shard_committees_at_slot ` and fix `test_demo`
2 parents b6da0b4 + d29578a commit 000333a

File tree

6 files changed

+96
-113
lines changed

6 files changed

+96
-113
lines changed

eth/beacon/helpers.py

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from typing import (
2-
Any,
32
Iterable,
43
Sequence,
54
Tuple,
@@ -63,47 +62,50 @@
6362
from eth.beacon.types.validator_records import ValidatorRecord # noqa: F401
6463

6564

66-
def _get_element_from_recent_list(
67-
target_list: Sequence[Any],
68-
target_slot: SlotNumber,
69-
slot_relative_position: SlotNumber) -> Any:
65+
#
66+
# Get block root
67+
#
68+
def _get_block_root(
69+
latest_block_roots: Sequence[Hash32],
70+
state_slot: SlotNumber,
71+
slot: SlotNumber,
72+
latest_block_roots_length: int) -> Hash32:
7073
"""
71-
Return the element from ``target_list`` by the ``target_slot`` number,
72-
where the the element should be at ``target_slot - slot_relative_position``th
73-
element of the given ``target_list``.
74+
Return the block root at a recent ``slot``.
7475
"""
75-
target_list_length = len(target_list)
76-
77-
if target_slot < slot_relative_position:
78-
raise ValueError(
79-
"target_slot (%s) should be greater than or equal to slot_relative_position (%s)" %
80-
(target_slot, slot_relative_position)
76+
if state_slot > slot + latest_block_roots_length:
77+
raise ValidationError(
78+
"state.slot ({}) should be less than or equal to "
79+
"(slot + latest_block_roots_length) ({}), "
80+
"where slot={}, latest_block_roots_length={}".format(
81+
state_slot,
82+
slot + latest_block_roots_length,
83+
slot,
84+
latest_block_roots_length,
85+
)
8186
)
82-
83-
if target_slot >= slot_relative_position + target_list_length:
84-
raise ValueError(
85-
"target_slot (%s) should be less than "
86-
"slot_relative_position (%s) + target_list_length (%s)" %
87-
(target_slot, slot_relative_position, target_list_length)
87+
if slot >= state_slot:
88+
raise ValidationError(
89+
"slot ({}) should be less than state.slot ({})".format(
90+
slot,
91+
state_slot,
92+
)
8893
)
89-
return target_list[target_slot - slot_relative_position]
94+
return latest_block_roots[slot % latest_block_roots_length]
9095

9196

92-
#
93-
# Get block root
94-
#
9597
def get_block_root(
96-
latest_block_roots: Sequence[Hash32],
97-
current_slot: SlotNumber,
98-
slot: SlotNumber) -> Hash32:
98+
state: 'BeaconState',
99+
slot: SlotNumber,
100+
latest_block_roots_length: int) -> Hash32:
99101
"""
100-
Returns the block root at a recent ``slot``.
102+
Return the block root at a recent ``slot``.
101103
"""
102-
slot_relative_position = SlotNumber(current_slot - len(latest_block_roots))
103-
return _get_element_from_recent_list(
104-
latest_block_roots,
104+
return _get_block_root(
105+
state.latest_block_roots,
106+
state.slot,
105107
slot,
106-
slot_relative_position,
108+
latest_block_roots_length,
107109
)
108110

109111

@@ -116,21 +118,29 @@ def _get_shard_committees_at_slot(
116118
shard_committees_at_slots: Sequence[Sequence[ShardCommittee]],
117119
slot: SlotNumber,
118120
epoch_length: int) -> Iterable[ShardCommittee]:
119-
if len(shard_committees_at_slots) != epoch_length * 2:
120-
raise ValueError(
121-
"Length of shard_committees_at_slots != epoch_length * 2"
122-
"\texpected: %s, found: %s" % (
123-
epoch_length * 2, len(shard_committees_at_slots)
121+
122+
earliest_slot_in_array = state_slot - (state_slot % epoch_length) - epoch_length
123+
124+
if earliest_slot_in_array > slot:
125+
raise ValidationError(
126+
"earliest_slot_in_array ({}) should be less than or equal to slot ({})".format(
127+
earliest_slot_in_array,
128+
slot,
129+
)
130+
)
131+
if slot >= earliest_slot_in_array + epoch_length * 2:
132+
raise ValidationError(
133+
"slot ({}) should be less than "
134+
"(earliest_slot_in_array + epoch_length * 2) ({}), "
135+
"where earliest_slot_in_array={}, epoch_length={}".format(
136+
slot,
137+
earliest_slot_in_array + epoch_length * 2,
138+
earliest_slot_in_array,
139+
epoch_length,
124140
)
125141
)
126142

127-
slot_relative_position = SlotNumber(state_slot - epoch_length)
128-
129-
yield from _get_element_from_recent_list(
130-
shard_committees_at_slots,
131-
slot,
132-
slot_relative_position,
133-
)
143+
return shard_committees_at_slots[slot - earliest_slot_in_array]
134144

135145

136146
def get_shard_committees_at_slot(state: 'BeaconState',

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def process_attestations(state: BeaconState,
2626
attestation,
2727
config.EPOCH_LENGTH,
2828
config.MIN_ATTESTATION_INCLUSION_DELAY,
29+
config.LATEST_BLOCK_ROOTS_LENGTH,
2930
)
3031

3132
# update_latest_attestations

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
ValidationError,
66
)
77
import rlp
8-
from typing import Type
98

109
from eth.constants import (
1110
ZERO_HASH32,
@@ -69,10 +68,11 @@ def validate_serenity_proposer_signature(state: BeaconState,
6968
#
7069
# Attestation validation
7170
#
72-
def validate_serenity_attestation(state: Type[BeaconState],
71+
def validate_serenity_attestation(state: BeaconState,
7372
attestation: Attestation,
7473
epoch_length: int,
75-
min_attestation_inclusion_delay: int) -> None:
74+
min_attestation_inclusion_delay: int,
75+
latest_block_roots_length: int) -> None:
7676
"""
7777
Validate the given ``attestation``.
7878
Raise ``ValidationError`` if it's invalid.
@@ -96,9 +96,9 @@ def validate_serenity_attestation(state: Type[BeaconState],
9696
validate_serenity_attestation_justified_block_root(
9797
attestation.data,
9898
justified_block_root=get_block_root(
99-
state.latest_block_roots,
100-
current_slot=state.slot,
99+
state=state,
101100
slot=attestation.data.justified_slot,
101+
latest_block_roots_length=latest_block_roots_length,
102102
),
103103
)
104104

@@ -237,7 +237,7 @@ def validate_serenity_attestation_shard_block_root(attestation_data: Attestation
237237
)
238238

239239

240-
def validate_serenity_attestation_aggregate_signature(state: Type[BeaconState],
240+
def validate_serenity_attestation_aggregate_signature(state: BeaconState,
241241
attestation: Attestation,
242242
epoch_length: int) -> None:
243243
"""

tests/beacon/state_machines/forks/test_serenity_operations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def create_mock_signed_attestations_at_slot(state,
4646
shard=shard_committee.shard,
4747
justified_slot=state.previous_justified_slot,
4848
justified_block_root=get_block_root(
49-
state.latest_block_roots,
50-
state.slot,
49+
state,
5150
state.previous_justified_slot,
51+
config.LATEST_BLOCK_ROOTS_LENGTH,
5252
),
5353
latest_crosslink_root=latest_crosslink_root,
5454
shard_block_root=ZERO_HASH32,

tests/beacon/state_machines/test_demo.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
'shard_count'
2727
),
2828
[
29-
(10, 2, 1, 2, 2)
29+
(10, 10, 1, 2, 2)
3030
]
3131
)
3232
def test_demo(base_db,
@@ -45,10 +45,7 @@ def test_demo(base_db,
4545

4646
# Sign block
4747
beacon_proposer_index = get_beacon_proposer_index(
48-
# TODO: use `state` when the bug of `get_shard_committees_at_slot` is fixed.
49-
state.copy(
50-
slot=state.slot + 2,
51-
),
48+
state,
5249
block.slot,
5350
config.EPOCH_LENGTH,
5451
)

tests/beacon/test_helpers.py

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,16 @@
3434
from eth.beacon.types.states import BeaconState
3535
from eth.beacon.types.validator_records import ValidatorRecord
3636
from eth.beacon.helpers import (
37-
_get_element_from_recent_list,
37+
_get_block_root,
38+
_get_shard_committees_at_slot,
3839
get_active_validator_indices,
3940
get_attestation_participants,
4041
get_beacon_proposer_index,
41-
get_block_root,
4242
get_effective_balance,
4343
get_domain,
4444
get_fork_version,
4545
get_new_shuffling,
4646
get_new_validator_registry_delta_chain_tip,
47-
_get_shard_committees_at_slot,
4847
get_block_committees_info,
4948
get_pubkey_for_indices,
5049
generate_aggregate_pubkeys,
@@ -88,56 +87,29 @@ def get_sample_shard_committees_at_slots(num_slot,
8887

8988
def generate_mock_latest_block_roots(
9089
genesis_block,
91-
current_block_number,
92-
epoch_length):
93-
chain_length = (current_block_number // epoch_length + 1) * epoch_length
90+
current_slot,
91+
epoch_length,
92+
latest_block_roots_length):
93+
assert current_slot < latest_block_roots_length
94+
95+
chain_length = (current_slot // epoch_length + 1) * epoch_length
9496
blocks = get_pseudo_chain(chain_length, genesis_block)
9597
latest_block_roots = [
96-
b'\x00' * 32
97-
for i
98-
in range(epoch_length * 2 - current_block_number)
99-
] + [block.root for block in blocks[:current_block_number]]
98+
block.hash
99+
for block in blocks[:current_slot]
100+
] + [
101+
ZERO_HASH32
102+
for _ in range(latest_block_roots_length - current_slot)
103+
]
100104
return blocks, latest_block_roots
101105

102106

103-
@pytest.mark.parametrize(
104-
(
105-
'target_list,target_slot,slot_relative_position,result'
106-
),
107-
[
108-
([i for i in range(5)], 10, 7, 3),
109-
([], 1, 1, ValueError()),
110-
# target_slot < slot_relative_position
111-
([i for i in range(5)], 1, 2, ValueError()),
112-
# target_slot >= slot_relative_position + target_list_length
113-
([i for i in range(5)], 6, 1, ValueError()),
114-
],
115-
)
116-
def test_get_element_from_recent_list(target_list,
117-
target_slot,
118-
slot_relative_position,
119-
result):
120-
if isinstance(result, Exception):
121-
with pytest.raises(ValueError):
122-
_get_element_from_recent_list(
123-
target_list,
124-
target_slot,
125-
slot_relative_position,
126-
)
127-
else:
128-
assert result == _get_element_from_recent_list(
129-
target_list,
130-
target_slot,
131-
slot_relative_position,
132-
)
133-
134-
135107
#
136108
# Get block rootes
137109
#
138110
@pytest.mark.parametrize(
139111
(
140-
'current_block_number,target_slot,success'
112+
'current_slot,target_slot,success'
141113
),
142114
[
143115
(10, 0, True),
@@ -148,30 +120,34 @@ def test_get_element_from_recent_list(target_list,
148120
(128, 128, False),
149121
],
150122
)
151-
def test_get_block_root(current_block_number,
123+
def test_get_block_root(current_slot,
152124
target_slot,
153125
success,
154126
epoch_length,
127+
latest_block_roots_length,
155128
sample_block):
156129
blocks, latest_block_roots = generate_mock_latest_block_roots(
157130
sample_block,
158-
current_block_number,
131+
current_slot,
159132
epoch_length,
133+
latest_block_roots_length,
160134
)
161135

162136
if success:
163-
block_root = get_block_root(
137+
block_root = _get_block_root(
164138
latest_block_roots,
165-
current_block_number,
139+
current_slot,
166140
target_slot,
141+
latest_block_roots_length,
167142
)
168143
assert block_root == blocks[target_slot].root
169144
else:
170-
with pytest.raises(ValueError):
171-
get_block_root(
145+
with pytest.raises(ValidationError):
146+
_get_block_root(
172147
latest_block_roots,
173-
current_block_number,
148+
current_slot,
174149
target_slot,
150+
latest_block_roots_length,
175151
)
176152

177153

@@ -207,15 +183,14 @@ def test_get_block_root(current_block_number,
207183
64,
208184
True,
209185
),
210-
# The length of shard_committees_at_slots != epoch_length * 2
211186
(
212187
100,
213188
64,
214-
64,
215-
127,
189+
1,
190+
128,
216191
10,
217-
0,
218-
False,
192+
1,
193+
True,
219194
),
220195
# slot is too small
221196
(
@@ -265,7 +240,7 @@ def test_get_shard_committees_at_slot(
265240
assert len(shard_committees) > 0
266241
assert len(shard_committees[0].committee) > 0
267242
else:
268-
with pytest.raises(ValueError):
243+
with pytest.raises(ValidationError):
269244
_get_shard_committees_at_slot(
270245
state_slot=state_slot,
271246
shard_committees_at_slots=shard_committees_at_slots,

0 commit comments

Comments
 (0)