1- from itertools import (
2- repeat ,
3- )
4-
51from typing import (
62 Any ,
73 Iterable ,
117)
128
139from eth_utils import (
10+ denoms ,
1411 to_tuple ,
12+ ValidationError ,
1513)
1614
1715from eth_typing import (
1816 Hash32 ,
1917)
2018
19+ from eth .utils .bitfield import (
20+ get_bitfield_length ,
21+ has_voted ,
22+ )
23+ from eth .utils .blake import (
24+ blake ,
25+ )
2126from eth .utils .numeric import (
2227 clamp ,
2328)
3641
3742
3843if TYPE_CHECKING :
39- from eth .beacon .types .active_states import ActiveState # noqa: F401
4044 from eth .beacon .types .attestation_records import AttestationRecord # noqa: F401
4145 from eth .beacon .types .blocks import BaseBeaconBlock # noqa: F401
42- from eth .beacon .types .crystallized_states import CrystallizedState # noqa: F401
4346 from eth .beacon .types .states import BeaconState # noqa: F401
4447 from eth .beacon .types .validator_records import ValidatorRecord # noqa: F401
4548
@@ -74,150 +77,80 @@ def _get_element_from_recent_list(
7477# Get block hash(es)
7578#
7679def 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 :
8183 """
82- Return the blockhash from ``ActiveState.recent_block_hashes`` by
83- ``current_block_slot_number``.
84+ Returns the block hash at a recent ``slot``.
8485 """
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 )
9487 return _get_element_from_recent_list (
95- recent_block_hashes ,
88+ latest_block_hashes ,
9689 slot ,
9790 slot_relative_position ,
9891 )
9992
10093
10194@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 ,
10598 from_slot : int ,
106- to_slot : int ,
107- epoch_length : int ) -> Iterable [Hash32 ]:
99+ to_slot : int ) -> Iterable [Hash32 ]:
108100 """
109101 Returns the block hashes between ``from_slot`` and ``to_slot``.
110102 """
111103 for slot in range (from_slot , to_slot + 1 ):
112104 yield get_block_hash (
113- recent_block_hashes ,
114- current_block_slot_number ,
105+ latest_block_hashes ,
106+ current_slot ,
115107 slot ,
116- epoch_length ,
117108 )
118109
119110
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-
169111#
170112# Get shards_committees or indices
171113#
172114@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 ]],
175118 slot : int ,
176119 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 :
181121 raise ValueError (
182- "Length of shard_committee_for_slots != epoch_length * 2"
122+ "Length of shard_committees_at_slots != epoch_length * 2"
183123 "\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 )
185125 )
186126 )
187127
188- slot_relative_position = crystallized_state . last_state_recalc - epoch_length
128+ slot_relative_position = latest_state_recalculation_slot - epoch_length
189129
190130 yield from _get_element_from_recent_list (
191- crystallized_state . shard_committee_for_slots ,
131+ shard_committees_at_slots ,
192132 slot ,
193133 slot_relative_position ,
194134 )
195135
196136
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 ]:
201140 """
202- FIXME
203- Return committee of the given attestation.
141+ Return the ``ShardCommittee`` for the ``slot``.
204142 """
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 ,
211148 )
212149
213- for shard_committee in shards_committees_for_slot :
214- if shard_committee .shard_id == shard_id :
215- yield from shard_committee .committee
216-
217150
218151def get_active_validator_indices (validators : Sequence ['ValidatorRecord' ]) -> Tuple [int , ...]:
219152 """
220- Gets indices of active validators from ``validators``.
153+ Get indices of active validators from ``validators``.
221154 """
222155 return tuple (
223156 i for i , v in enumerate (validators )
@@ -235,7 +168,7 @@ def _get_shards_committees_for_shard_indices(
235168 total_validator_count : int ,
236169 shard_count : int ) -> Iterable [ShardCommittee ]:
237170 """
238- Returns filled [ShardCommittee] tuple.
171+ Return filled [ShardCommittee] tuple.
239172 """
240173 for index , indices in enumerate (shard_indices ):
241174 yield ShardCommittee (
@@ -320,45 +253,143 @@ def get_new_shuffling(*,
320253
321254
322255#
323- # Get proposer postition
256+ # Get proposer position
324257#
325258def get_block_committees_info (parent_block : 'BaseBeaconBlock' ,
326- crystallized_state : 'CrystallizedState ' ,
259+ state : 'BeaconState ' ,
327260 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 ,
331264 epoch_length ,
332265 )
333266 """
334- FIXME
335267 Return the block committees and proposer info with BlockCommitteesInfo pack.
336268 """
337269 # `proposer_index_in_committee` th attester in `shard_committee`
338270 # is the proposer of the parent block.
339271 try :
340272 shard_committee = shards_committees [0 ]
341273 except IndexError :
342- raise ValueError ("shards_committees should not be empty." )
274+ raise ValidationError ("shards_committees should not be empty." )
343275
344276 proposer_committee_size = len (shard_committee .committee )
345277 if proposer_committee_size <= 0 :
346- raise ValueError (
278+ raise ValidationError (
347279 "The first committee should not be empty"
348280 )
349281
350282 proposer_index_in_committee = (
351- parent_block .slot_number %
283+ parent_block .slot %
352284 proposer_committee_size
353285 )
354286
355- # The index in CrystallizedState.validators
356287 proposer_index = shard_committee .committee [proposer_index_in_committee ]
357288
358289 return BlockCommitteesInfo (
359290 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 ,
362292 proposer_committee_size = proposer_committee_size ,
363293 shards_committees = shards_committees ,
364294 )
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