Skip to content

Commit b1bfa61

Browse files
committed
cleanup some bugs in attestation testing.
1 parent 4bf22ed commit b1bfa61

File tree

9 files changed

+96
-71
lines changed

9 files changed

+96
-71
lines changed

eth/beacon/helpers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ def get_block_root(
8484
"""
8585
Returns the block root at a recent ``slot``.
8686
"""
87-
slot_relative_position = max(current_slot - len(latest_block_roots), 0)
87+
slot_relative_position = current_slot - len(latest_block_roots)
88+
# slot_relative_position = max(current_slot - len(latest_block_roots), 0)
8889
return _get_element_from_recent_list(
8990
latest_block_roots,
9091
slot,
@@ -109,7 +110,7 @@ def _get_shard_committees_at_slot(
109110
)
110111
)
111112

112-
slot_relative_position = max(state_slot - epoch_length, 0)
113+
slot_relative_position = state_slot - epoch_length
113114

114115
yield from _get_element_from_recent_list(
115116
shard_committees_at_slots,

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from eth_typing import (
2+
Hash32,
3+
)
4+
15
from eth.beacon.types.blocks import BaseBeaconBlock
26
from eth.beacon.types.states import BeaconState
37

@@ -16,14 +20,22 @@ def __init__(self, config: BeaconConfig):
1620
self.config = config
1721

1822
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)
23+
while state.slot != block.slot:
24+
state = self.per_slot_transition(state, block.parent_root)
25+
if state.slot == block.slot:
26+
state = self.per_block_transition(state, block)
27+
if state.slot % self.config.EPOCH_LENGTH == 0:
28+
state = self.per_epoch_transition(state)
2229

2330
return state
2431

25-
def per_slot_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
32+
def per_slot_transition(self,
33+
state: BeaconState,
34+
previous_block_root: Hash32) -> BeaconState:
2635
# TODO
36+
state = state.copy(
37+
slot=state.slot + 1
38+
)
2739
return state
2840

2941
def per_block_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ def validate_serenity_attestation_latest_crosslink_root(attestation_data: Attest
168168
field of ``attestation_data`` is the provided ``latest_crosslink_root``.
169169
Raise ``ValidationError`` if it's invalid.
170170
"""
171-
acceptable_shard_block_roots = [
171+
acceptable_shard_block_roots = {
172172
attestation_data.latest_crosslink_root,
173173
attestation_data.shard_block_root,
174-
]
174+
}
175175
if latest_crosslink_root not in acceptable_shard_block_roots:
176176
raise ValidationError(
177177
"Neither the attestation ``latest_crosslink_root`` nor the attestation "
@@ -229,6 +229,8 @@ def validate_serenity_attestation_aggregate_signature(state: Type[BeaconState],
229229
)
230230
group_public_key = bls.aggregate_pubkeys(pubkeys)
231231

232+
# TODO: change to tree hashing when we have SSZ
233+
# TODO: Replace with AttestationAndCustodyBit data structure
232234
message = hash_eth2(
233235
rlp.encode(attestation.data) +
234236
(0).to_bytes(1, "big")

eth/beacon/state_machines/state_transitions.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
abstractmethod,
44
)
55

6+
from eth_typing import (
7+
Hash32,
8+
)
69
from eth._utils.datatypes import (
710
Configurable,
811
)
912

10-
from eth.beacon.types.attestations import Attestation
1113
from eth.beacon.types.blocks import BaseBeaconBlock
1214
from eth.beacon.types.states import BeaconState
1315

@@ -25,22 +27,15 @@ def apply_state_transition(self, state: BeaconState, block: BaseBeaconBlock) ->
2527
pass
2628

2729
@abstractmethod
28-
def per_slot_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
30+
def per_slot_transition(self,
31+
state: BeaconState,
32+
previous_block_root: Hash32) -> BeaconState:
2933
pass
3034

3135
@abstractmethod
3236
def per_block_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
3337
pass
3438

3539
@abstractmethod
36-
def per_epoch_transition(self, state: BeaconState, block: BaseBeaconBlock) -> BeaconState:
40+
def per_epoch_transition(self, state: BeaconState) -> BeaconState:
3741
pass
38-
39-
#
40-
# Operation validations
41-
#
42-
@abstractmethod
43-
def validate_attestation(self,
44-
attestation: Attestation,
45-
is_validating_signatures: bool=True) -> None:
46-
raise NotImplementedError

tests/beacon/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,4 +599,3 @@ def create_mock_signed_attestation(state,
599599
)
600600

601601
return create_mock_signed_attestation
602-

tests/beacon/state_machines/test_attestation_validation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ def test_validate_serenity_attestation_aggregate_signature(genesis_state,
244244
random,
245245
sample_attestation_data_params,
246246
create_mock_signed_attestation,
247-
config,
248247
is_valid):
249248
state = genesis_state
250249

tests/beacon/state_machines/test_demo.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55

66
def test_demo(base_db, sample_beacon_block_params, sample_beacon_state_params, fixture_sm_class):
77
chaindb = BeaconChainDB(base_db)
8-
block = BaseBeaconBlock(**sample_beacon_block_params)
98
state = BeaconState(**sample_beacon_state_params)
9+
block = BaseBeaconBlock(**sample_beacon_block_params).copy(
10+
slot=state.slot + 2,
11+
)
1012

1113
sm = fixture_sm_class(chaindb, block, state)
1214
result_state, result_block = sm.import_block(block)
1315

1416
assert state.slot == 0
15-
assert result_state.slot == sm.config.ZERO_BALANCE_VALIDATOR_TTL
17+
assert result_state.slot == block.slot

tests/beacon/state_machines/test_serenity_operations.py

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from eth.beacon.helpers import (
1212
get_block_root,
13+
get_shard_committees_at_slot,
1314
)
1415

1516
from eth.beacon.types.attestation_data import AttestationData
@@ -20,6 +21,49 @@
2021
)
2122

2223

24+
@pytest.fixture
25+
def create_mock_signed_attestations_at_slot(config,
26+
sample_attestation_data_params,
27+
create_mock_signed_attestation):
28+
def create_mock_signed_attestations_at_slot(state,
29+
attestation_slot):
30+
attestations = []
31+
shard_and_committees_at_slot = get_shard_committees_at_slot(
32+
state,
33+
slot=attestation_slot,
34+
epoch_length=config.EPOCH_LENGTH,
35+
)
36+
for shard_committee in shard_and_committees_at_slot:
37+
# have 0th committee member sign
38+
voting_committee_indices = [0]
39+
latest_crosslink_root = state.latest_crosslinks[shard_committee.shard].shard_block_root
40+
41+
assert len(shard_committee.committee) > 0
42+
attestation_data = AttestationData(**sample_attestation_data_params).copy(
43+
slot=attestation_slot,
44+
shard=shard_committee.shard,
45+
justified_slot=state.previous_justified_slot,
46+
justified_block_root=get_block_root(
47+
state.latest_block_roots,
48+
state.slot,
49+
state.previous_justified_slot,
50+
),
51+
latest_crosslink_root=latest_crosslink_root,
52+
shard_block_root=ZERO_HASH32,
53+
)
54+
55+
attestations.append(
56+
create_mock_signed_attestation(
57+
state,
58+
shard_committee,
59+
voting_committee_indices,
60+
attestation_data,
61+
)
62+
)
63+
return tuple(attestations)
64+
return create_mock_signed_attestations_at_slot
65+
66+
2367
@pytest.mark.parametrize(
2468
(
2569
'num_validators,'
@@ -40,7 +84,7 @@ def test_process_attestations(genesis_state,
4084
sample_beacon_block_params,
4185
sample_beacon_block_body_params,
4286
config,
43-
create_mock_signed_attestation,
87+
create_mock_signed_attestations_at_slot,
4488
success):
4589

4690
attestation_slot = 0
@@ -49,71 +93,43 @@ def test_process_attestations(genesis_state,
4993
slot=current_slot,
5094
)
5195

52-
attestations = []
53-
for shard_committee in state.shard_committees_at_slots[attestation_slot]:
54-
# have 0th committee member sign
55-
voting_committee_indices = [0]
56-
latest_crosslink_root = state.latest_crosslinks[shard_committee.shard].shard_block_root
57-
58-
assert len(shard_committee.committee) > 0
59-
attestation_data = AttestationData(**sample_attestation_data_params).copy(
60-
slot=attestation_slot,
61-
shard=shard_committee.shard,
62-
justified_slot=state.previous_justified_slot,
63-
justified_block_root=get_block_root(
64-
state.latest_block_roots,
65-
state.slot,
66-
state.previous_justified_slot,
67-
),
68-
latest_crosslink_root=latest_crosslink_root,
69-
shard_block_root=ZERO_HASH32,
70-
)
71-
72-
attestations.append(
73-
create_mock_signed_attestation(
74-
state,
75-
shard_committee,
76-
voting_committee_indices,
77-
attestation_data,
78-
)
79-
)
96+
attestations = create_mock_signed_attestations_at_slot(
97+
state,
98+
attestation_slot,
99+
)
80100

81101
assert len(attestations) > 0
82102

83103
if not success:
84104
# create invalid attestation in the future
85-
bad_attestation_data = AttestationData(**sample_attestation_data_params).copy(
105+
invalid_attestation_data = attestations[-1].data.copy(
86106
slot=state.slot + 10,
87107
)
88-
attestations.append(
89-
create_mock_signed_attestation(
90-
state,
91-
state.shard_committees_at_slots[attestation_slot][0],
92-
[0],
93-
bad_attestation_data,
94-
)
108+
invalid_attestation = attestations[-1].copy(
109+
data=invalid_attestation_data,
95110
)
111+
attestations = attestations[:-1] + (invalid_attestation,)
96112

97113
block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
98114
attestations=attestations,
99115
)
100116
block = BaseBeaconBlock(**sample_beacon_block_params).copy(
101117
slot=current_slot,
102-
body=block_body
118+
body=block_body,
103119
)
104120

105121
if success:
106122
new_state = process_attestations(
107123
state,
108124
block,
109-
config
125+
config,
110126
)
111127

112128
assert len(new_state.latest_attestations) == len(attestations)
113129
else:
114130
with pytest.raises(ValidationError):
115-
new_state = process_attestations(
131+
process_attestations(
116132
state,
117133
block,
118-
config
134+
config,
119135
)

tests/beacon/test_helpers.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,11 @@ def test_get_element_from_recent_list(target_list,
131131
(128, 128, False),
132132
],
133133
)
134-
def test_get_block_root(
135-
current_block_number,
136-
target_slot,
137-
success,
138-
epoch_length,
139-
sample_block):
134+
def test_get_block_root(current_block_number,
135+
target_slot,
136+
success,
137+
epoch_length,
138+
sample_block):
140139
blocks, latest_block_roots = generate_mock_latest_block_roots(
141140
sample_block,
142141
current_block_number,

0 commit comments

Comments
 (0)