1
- from itertools import (
2
- repeat ,
3
- )
4
-
5
1
from typing import (
6
2
Any ,
7
3
Iterable ,
11
7
)
12
8
13
9
from eth_utils import (
10
+ denoms ,
14
11
to_tuple ,
12
+ ValidationError ,
15
13
)
16
14
17
15
from eth_typing import (
18
16
Hash32 ,
19
17
)
20
18
19
+ from eth .utils .bitfield import (
20
+ get_bitfield_length ,
21
+ has_voted ,
22
+ )
23
+ from eth .utils .blake import (
24
+ blake ,
25
+ )
21
26
from eth .utils .numeric import (
22
27
clamp ,
23
28
)
36
41
37
42
38
43
if TYPE_CHECKING :
39
- from eth .beacon .types .active_states import ActiveState # noqa: F401
40
44
from eth .beacon .types .attestation_records import AttestationRecord # noqa: F401
41
45
from eth .beacon .types .blocks import BaseBeaconBlock # noqa: F401
42
- from eth .beacon .types .crystallized_states import CrystallizedState # noqa: F401
43
46
from eth .beacon .types .states import BeaconState # noqa: F401
44
47
from eth .beacon .types .validator_records import ValidatorRecord # noqa: F401
45
48
@@ -74,150 +77,80 @@ def _get_element_from_recent_list(
74
77
# Get block hash(es)
75
78
#
76
79
def get_block_hash (
77
- recent_block_hashes : Sequence [Hash32 ],
78
- current_block_slot_number : int ,
79
- slot : int ,
80
- epoch_length : int ) -> Hash32 :
80
+ latest_block_hashes : Sequence [Hash32 ],
81
+ current_slot : int ,
82
+ slot : int ) -> Hash32 :
81
83
"""
82
- Return the blockhash from ``ActiveState.recent_block_hashes`` by
83
- ``current_block_slot_number``.
84
+ Returns the block hash at a recent ``slot``.
84
85
"""
85
- if len (recent_block_hashes ) != epoch_length * 2 :
86
- raise ValueError (
87
- "Length of recent_block_hashes != epoch_length * 2"
88
- "\t expected: %s, found: %s" % (
89
- epoch_length * 2 , len (recent_block_hashes )
90
- )
91
- )
92
-
93
- slot_relative_position = current_block_slot_number - epoch_length * 2
86
+ slot_relative_position = current_slot - len (latest_block_hashes )
94
87
return _get_element_from_recent_list (
95
- recent_block_hashes ,
88
+ latest_block_hashes ,
96
89
slot ,
97
90
slot_relative_position ,
98
91
)
99
92
100
93
101
94
@to_tuple
102
- def get_hashes_from_recent_block_hashes (
103
- recent_block_hashes : Sequence [Hash32 ],
104
- current_block_slot_number : int ,
95
+ def get_hashes_from_latest_block_hashes (
96
+ latest_block_hashes : Sequence [Hash32 ],
97
+ current_slot : int ,
105
98
from_slot : int ,
106
- to_slot : int ,
107
- epoch_length : int ) -> Iterable [Hash32 ]:
99
+ to_slot : int ) -> Iterable [Hash32 ]:
108
100
"""
109
101
Returns the block hashes between ``from_slot`` and ``to_slot``.
110
102
"""
111
103
for slot in range (from_slot , to_slot + 1 ):
112
104
yield get_block_hash (
113
- recent_block_hashes ,
114
- current_block_slot_number ,
105
+ latest_block_hashes ,
106
+ current_slot ,
115
107
slot ,
116
- epoch_length ,
117
108
)
118
109
119
110
120
- @to_tuple
121
- def get_hashes_to_sign (recent_block_hashes : Sequence [Hash32 ],
122
- block : 'BaseBeaconBlock' ,
123
- epoch_length : int ) -> Iterable [Hash32 ]:
124
- """
125
- Given the head block to attest to, collect the list of hashes to be
126
- signed in the attestation.
127
- """
128
- yield from get_hashes_from_recent_block_hashes (
129
- recent_block_hashes ,
130
- block .slot_number ,
131
- from_slot = block .slot_number - epoch_length + 1 ,
132
- to_slot = block .slot_number - 1 ,
133
- epoch_length = epoch_length ,
134
- )
135
- yield block .hash
136
-
137
-
138
- @to_tuple
139
- def get_signed_parent_hashes (recent_block_hashes : Sequence [Hash32 ],
140
- block : 'BaseBeaconBlock' ,
141
- attestation : 'AttestationRecord' ,
142
- epoch_length : int ) -> Iterable [Hash32 ]:
143
- """
144
- Given an attestation and the block they were included in,
145
- the list of hashes that were included in the signature.
146
- """
147
- yield from get_hashes_from_recent_block_hashes (
148
- recent_block_hashes ,
149
- block .slot_number ,
150
- from_slot = attestation .slot - epoch_length + 1 ,
151
- to_slot = attestation .slot - len (attestation .oblique_parent_hashes ),
152
- epoch_length = epoch_length ,
153
- )
154
- yield from attestation .oblique_parent_hashes
155
-
156
-
157
- @to_tuple
158
- def get_new_recent_block_hashes (old_block_hashes : Sequence [Hash32 ],
159
- parent_slot : int ,
160
- current_slot : int ,
161
- parent_hash : Hash32 ) -> Iterable [Hash32 ]:
162
-
163
- shift_size = current_slot - parent_slot
164
- parent_hash_repeat = min (shift_size , len (old_block_hashes ))
165
- yield from old_block_hashes [shift_size :]
166
- yield from repeat (parent_hash , parent_hash_repeat )
167
-
168
-
169
111
#
170
112
# Get shards_committees or indices
171
113
#
172
114
@to_tuple
173
- def get_shards_committees_for_slot (
174
- crystallized_state : 'CrystallizedState' ,
115
+ def _get_shard_committees_at_slot (
116
+ latest_state_recalculation_slot : int ,
117
+ shard_committees_at_slots : Sequence [Sequence [ShardCommittee ]],
175
118
slot : int ,
176
119
epoch_length : int ) -> Iterable [ShardCommittee ]:
177
- """
178
- FIXME
179
- """
180
- if len (crystallized_state .shard_committee_for_slots ) != epoch_length * 2 :
120
+ if len (shard_committees_at_slots ) != epoch_length * 2 :
181
121
raise ValueError (
182
- "Length of shard_committee_for_slots != epoch_length * 2"
122
+ "Length of shard_committees_at_slots != epoch_length * 2"
183
123
"\t expected: %s, found: %s" % (
184
- epoch_length * 2 , len (crystallized_state . shard_committee_for_slots )
124
+ epoch_length * 2 , len (shard_committees_at_slots )
185
125
)
186
126
)
187
127
188
- slot_relative_position = crystallized_state . last_state_recalc - epoch_length
128
+ slot_relative_position = latest_state_recalculation_slot - epoch_length
189
129
190
130
yield from _get_element_from_recent_list (
191
- crystallized_state . shard_committee_for_slots ,
131
+ shard_committees_at_slots ,
192
132
slot ,
193
133
slot_relative_position ,
194
134
)
195
135
196
136
197
- @to_tuple
198
- def get_attestation_indices (crystallized_state : 'CrystallizedState' ,
199
- attestation : 'AttestationRecord' ,
200
- epoch_length : int ) -> Iterable [int ]:
137
+ def get_shard_committees_at_slot (state : 'BeaconState' ,
138
+ slot : int ,
139
+ epoch_length : int ) -> Tuple [ShardCommittee ]:
201
140
"""
202
- FIXME
203
- Return committee of the given attestation.
141
+ Return the ``ShardCommittee`` for the ``slot``.
204
142
"""
205
- shard_id = attestation .shard_id
206
-
207
- shards_committees_for_slot = get_shards_committees_for_slot (
208
- crystallized_state ,
209
- attestation .slot ,
210
- epoch_length ,
143
+ return _get_shard_committees_at_slot (
144
+ latest_state_recalculation_slot = state .latest_state_recalculation_slot ,
145
+ shard_committees_at_slots = state .shard_committees_at_slots ,
146
+ slot = slot ,
147
+ epoch_length = epoch_length ,
211
148
)
212
149
213
- for shard_committee in shards_committees_for_slot :
214
- if shard_committee .shard_id == shard_id :
215
- yield from shard_committee .committee
216
-
217
150
218
151
def get_active_validator_indices (validators : Sequence ['ValidatorRecord' ]) -> Tuple [int , ...]:
219
152
"""
220
- Gets indices of active validators from ``validators``.
153
+ Get indices of active validators from ``validators``.
221
154
"""
222
155
return tuple (
223
156
i for i , v in enumerate (validators )
@@ -235,7 +168,7 @@ def _get_shards_committees_for_shard_indices(
235
168
total_validator_count : int ,
236
169
shard_count : int ) -> Iterable [ShardCommittee ]:
237
170
"""
238
- Returns filled [ShardCommittee] tuple.
171
+ Return filled [ShardCommittee] tuple.
239
172
"""
240
173
for index , indices in enumerate (shard_indices ):
241
174
yield ShardCommittee (
@@ -320,45 +253,143 @@ def get_new_shuffling(*,
320
253
321
254
322
255
#
323
- # Get proposer postition
256
+ # Get proposer position
324
257
#
325
258
def get_block_committees_info (parent_block : 'BaseBeaconBlock' ,
326
- crystallized_state : 'CrystallizedState ' ,
259
+ state : 'BeaconState ' ,
327
260
epoch_length : int ) -> BlockCommitteesInfo :
328
- shards_committees = get_shards_committees_for_slot (
329
- crystallized_state ,
330
- parent_block .slot_number ,
261
+ shards_committees = get_shard_committees_at_slot (
262
+ state ,
263
+ parent_block .slot ,
331
264
epoch_length ,
332
265
)
333
266
"""
334
- FIXME
335
267
Return the block committees and proposer info with BlockCommitteesInfo pack.
336
268
"""
337
269
# `proposer_index_in_committee` th attester in `shard_committee`
338
270
# is the proposer of the parent block.
339
271
try :
340
272
shard_committee = shards_committees [0 ]
341
273
except IndexError :
342
- raise ValueError ("shards_committees should not be empty." )
274
+ raise ValidationError ("shards_committees should not be empty." )
343
275
344
276
proposer_committee_size = len (shard_committee .committee )
345
277
if proposer_committee_size <= 0 :
346
- raise ValueError (
278
+ raise ValidationError (
347
279
"The first committee should not be empty"
348
280
)
349
281
350
282
proposer_index_in_committee = (
351
- parent_block .slot_number %
283
+ parent_block .slot %
352
284
proposer_committee_size
353
285
)
354
286
355
- # The index in CrystallizedState.validators
356
287
proposer_index = shard_committee .committee [proposer_index_in_committee ]
357
288
358
289
return BlockCommitteesInfo (
359
290
proposer_index = proposer_index ,
360
- proposer_index_in_committee = proposer_index_in_committee ,
361
- proposer_shard_id = shard_committee .shard_id ,
291
+ proposer_shard = shard_committee .shard ,
362
292
proposer_committee_size = proposer_committee_size ,
363
293
shards_committees = shards_committees ,
364
294
)
295
+
296
+
297
+ def get_beacon_proposer_index (state : 'BeaconState' ,
298
+ slot : int ,
299
+ epoch_length : int ) -> int :
300
+ """
301
+ Return the beacon proposer index for the ``slot``.
302
+ """
303
+ shard_committees = get_shard_committees_at_slot (
304
+ state ,
305
+ slot ,
306
+ epoch_length ,
307
+ )
308
+ try :
309
+ first_shard_committee = shard_committees [0 ]
310
+ except IndexError :
311
+ raise ValidationError ("shard_committees should not be empty." )
312
+
313
+ proposer_committee_size = len (first_shard_committee .committee )
314
+
315
+ if proposer_committee_size <= 0 :
316
+ raise ValidationError (
317
+ "The first committee should not be empty"
318
+ )
319
+
320
+ return first_shard_committee .committee [slot % len (first_shard_committee .committee )]
321
+
322
+
323
+ #
324
+ # Bitfields
325
+ #
326
+ @to_tuple
327
+ def get_attestation_participants (state : 'BeaconState' ,
328
+ slot : int ,
329
+ shard : int ,
330
+ participation_bitfield : bytes ,
331
+ epoch_length : int ) -> Iterable [int ]:
332
+ """
333
+ Return the participants' indices at the ``slot`` of shard ``shard``
334
+ from ``participation_bitfield``.
335
+ """
336
+ # Find the relevant committee
337
+ # Filter by slot
338
+ shard_committees_at_slot = get_shard_committees_at_slot (
339
+ state ,
340
+ slot ,
341
+ epoch_length ,
342
+ )
343
+ # Filter by shard
344
+ shard_committees = tuple (
345
+ [
346
+ shard_committee
347
+ for shard_committee in shard_committees_at_slot
348
+ if shard_committee .shard == shard
349
+ ]
350
+ )
351
+
352
+ try :
353
+ shard_committee = shard_committees [0 ]
354
+ except IndexError :
355
+ raise ValidationError ("shard_committees should not be empty." )
356
+
357
+ if len (participation_bitfield ) != get_bitfield_length (len (shard_committee .committee )):
358
+ raise ValidationError (
359
+ 'Invalid bitfield length,'
360
+ "\t expected: %s, found: %s" % (
361
+ get_bitfield_length (len (shard_committee .committee )),
362
+ len (participation_bitfield ),
363
+ )
364
+ )
365
+
366
+ # Find the participating attesters in the committee
367
+ for bitfield_index , validator_index in enumerate (shard_committee .committee ):
368
+ if has_voted (participation_bitfield , bitfield_index ):
369
+ yield validator_index
370
+
371
+
372
+ #
373
+ # Misc
374
+ #
375
+ def get_effective_balance (validator : 'ValidatorRecord' , max_deposit : int ) -> int :
376
+ """
377
+ Return the effective balance (also known as "balance at stake") for the ``validator``.
378
+ """
379
+ return min (validator .balance , max_deposit * denoms .gwei )
380
+
381
+
382
+ def get_new_validator_registry_delta_chain_tip (current_validator_registry_delta_chain_tip : Hash32 ,
383
+ index : int ,
384
+ pubkey : int ,
385
+ flag : int ) -> Hash32 :
386
+ """
387
+ Compute the next hash in the validator registry delta hash chain.
388
+ """
389
+ return blake (
390
+ current_validator_registry_delta_chain_tip +
391
+ flag .to_bytes (1 , 'big' ) +
392
+ index .to_bytes (3 , 'big' ) +
393
+ # TODO: currently, we use 256-bit pubkey which is different form the spec
394
+ pubkey .to_bytes (32 , 'big' )
395
+ )
0 commit comments