66from collections .abc import Set as AbstractSet
77from typing import TYPE_CHECKING
88
9- from lean_spec .subspecs .chain .clock import Interval
10- from lean_spec .subspecs .chain .config import INTERVALS_PER_SLOT
119from lean_spec .subspecs .ssz .hash import hash_tree_root
1210from lean_spec .subspecs .xmss .aggregation import AggregatedSignatureProof
1311from lean_spec .subspecs .xmss .containers import PublicKey , Signature
3533)
3634
3735if TYPE_CHECKING :
38- from lean_spec .subspecs .forkchoice import GossipSignatureEntry , Store
36+ from lean_spec .subspecs .forkchoice import GossipSignatureEntry
3937
4038
4139class State (Container ):
@@ -81,16 +79,11 @@ def generate_genesis(cls, genesis_time: Uint64, validators: Validators) -> State
8179 """
8280 Generate a genesis state with empty history and proper initial values.
8381
84- Parameters
85- ----------
86- genesis_time : Uint64
87- The genesis timestamp.
88- validators : Validators
89- The list of validators in the genesis state.
82+ Args:
83+ genesis_time: The genesis timestamp.
84+ validators: The list of validators in the genesis state.
9085
9186 Returns:
92- -------
93- State
9487 A properly initialized genesis state.
9588 """
9689 # Configure the genesis state.
@@ -121,71 +114,6 @@ def generate_genesis(cls, genesis_time: Uint64, validators: Validators) -> State
121114 justifications_validators = JustificationValidators (data = []),
122115 )
123116
124- def to_forkchoice_store (
125- self ,
126- anchor_block : Block ,
127- validator_id : ValidatorIndex | None ,
128- ) -> Store :
129- """
130- Initialize a forkchoice store from this state and an anchor block.
131-
132- The anchor block and this state form the starting point for fork choice.
133- Both are treated as justified and finalized.
134-
135- Args:
136- anchor_block: A trusted block (e.g. genesis or checkpoint).
137- validator_id: Index of the validator running this store.
138-
139- Returns:
140- A new Store instance, ready to accept blocks and attestations.
141-
142- Raises:
143- AssertionError:
144- If the anchor block's state root does not match the hash
145- of this state.
146- """
147- from lean_spec .subspecs .forkchoice import Store
148-
149- # Compute the SSZ root of this state.
150- #
151- # This is the canonical hash that should appear in the block's state root.
152- computed_state_root = hash_tree_root (self )
153-
154- # Check that the block actually points to this state.
155- #
156- # If this fails, the caller has supplied inconsistent inputs.
157- assert anchor_block .state_root == computed_state_root , (
158- "Anchor block state root must match anchor state hash"
159- )
160-
161- # Compute the SSZ root of the anchor block itself.
162- #
163- # This root will be used as:
164- # - the key in the blocks/states maps,
165- # - the initial head,
166- # - the root of the initial checkpoints.
167- anchor_root = hash_tree_root (anchor_block )
168-
169- # Read the slot at which the anchor block was proposed.
170- anchor_slot = anchor_block .slot
171-
172- # Initialize checkpoints from this state.
173- #
174- # We explicitly set the root to the anchor block root.
175- # The state internally might have zero-hash checkpoints (if genesis),
176- # but the Store must treat the anchor block as the justified/finalized point.
177- return Store (
178- time = Interval (anchor_slot * INTERVALS_PER_SLOT ),
179- config = self .config ,
180- head = anchor_root ,
181- safe_target = anchor_root ,
182- latest_justified = self .latest_justified .model_copy (update = {"root" : anchor_root }),
183- latest_finalized = self .latest_finalized .model_copy (update = {"root" : anchor_root }),
184- blocks = {anchor_root : anchor_block },
185- states = {anchor_root : self },
186- validator_id = validator_id ,
187- )
188-
189117 def process_slots (self , target_slot : Slot ) -> State :
190118 """
191119 Advance the state through empty slots up to, but not including, target_slot.
@@ -195,20 +123,14 @@ def process_slots(self, target_slot: Slot) -> State:
195123 - Increments the slot counter after each call.
196124 The function returns a new state with slot == target_slot.
197125
198- Parameters
199- ----------
200- target_slot : Slot
201- The slot to reach by processing empty slots.
126+ Args:
127+ target_slot: The slot to reach by processing empty slots.
202128
203129 Returns:
204- -------
205- State
206130 A new state that has progressed to target_slot.
207131
208132 Raises:
209- ------
210- AssertionError
211- If target_slot is not in the future.
133+ AssertionError: If target_slot is not in the future.
212134 """
213135 # The target must be strictly greater than the current slot.
214136 assert self .slot < target_slot , "Target slot must be in the future"
@@ -278,20 +200,14 @@ def process_block_header(self, block: Block) -> State:
278200 - Insert ZERO_HASH entries for any skipped empty slots.
279201 - Set latest_block_header for the new block with an empty state_root.
280202
281- Parameters
282- ----------
283- block : Block
284- The block whose header is being processed.
203+ Args:
204+ block: The block whose header is being processed.
285205
286206 Returns:
287- -------
288- State
289207 A new state with header-related fields updated.
290208
291209 Raises:
292- ------
293- AssertionError
294- If any header check fails.
210+ AssertionError: If any header check fails.
295211 """
296212 # Validation
297213 #
@@ -414,20 +330,15 @@ def process_block(self, block: Block) -> State:
414330 """
415331 Apply full block processing including header and body.
416332
417- Parameters
418- ----------
419- block : Block
420- The block to process.
333+ Args:
334+ block: The block to process.
421335
422336 Returns:
423- -------
424- State
425337 A new state with the processed block.
426338
427339 Raises:
428- ------
429- AssertionError
430- If block contains duplicate aggregated attestations with no unique participant.
340+ AssertionError: If block contains duplicate aggregated attestations
341+ with no unique participant.
431342 """
432343 # First process the block header.
433344 state = self .process_block_header (block )
@@ -447,14 +358,10 @@ def process_attestations(
447358 2. Updates justified status for target checkpoints
448359 3. Applies finalization rules based on justified status
449360
450- Parameters
451- ----------
452- attestations : Iterable[AggregatedAttestation]
453- The aggregated attestations to process.
361+ Args:
362+ attestations: The aggregated attestations to process.
454363
455364 Returns:
456- -------
457- State
458365 A new state with updated justification/finalization.
459366 """
460367 # Reconstruct the vote-tracking structure
@@ -696,22 +603,15 @@ def state_transition(self, block: Block, valid_signatures: bool = True) -> State
696603 3. Process the block header and body
697604 4. Validate the computed state root
698605
699- Parameters
700- ----------
701- block : Block
702- The block to apply to the state.
703- valid_signatures : bool, optional
704- Whether to validate block signatures. Defaults to True.
606+ Args:
607+ block: The block to apply to the state.
608+ valid_signatures: Whether to validate block signatures. Defaults to True.
705609
706610 Returns:
707- -------
708- State
709611 A new state after applying the block.
710612
711613 Raises:
712- ------
713- AssertionError
714- If signature validation fails or state root is invalid.
614+ AssertionError: If signature validation fails or state root is invalid.
715615 """
716616 # Validate signatures if required
717617 if not valid_signatures :
@@ -871,18 +771,13 @@ def aggregate_gossip_signatures(
871771 from the gossip network. These are fresh signatures that validators
872772 broadcast when they attest.
873773
874- Parameters
875- ----------
876- attestations : Collection[Attestation]
877- Individual attestations to aggregate and sign.
878- gossip_signatures : dict[AttestationData, set[GossipSignatureEntry]] | None
879- Per-validator XMSS signatures learned from the gossip network,
880- keyed by the attestation data they signed.
774+ Args:
775+ attestations: Individual attestations to aggregate and sign.
776+ gossip_signatures: Per-validator XMSS signatures learned from
777+ the gossip network, keyed by the attestation data they signed.
881778
882779 Returns:
883- -------
884- list[tuple[AggregatedAttestation, AggregatedSignatureProof]]
885- - List of (attestation, proof) pairs from gossip collection.
780+ List of (attestation, proof) pairs from gossip collection.
886781 """
887782 results : list [tuple [AggregatedAttestation , AggregatedSignatureProof ]] = []
888783
@@ -955,16 +850,11 @@ def select_aggregated_proofs(
955850 For each attestation group, greedily pick proofs that cover the most
956851 remaining validators until all are covered or no more proofs exist.
957852
958- Parameters:
959- ----------
960- attestations : list[Attestation]
961- Individual attestations to aggregate and sign.
962- aggregated_payloads : dict[AttestationData, set[AggregatedSignatureProof]] | None
963- Aggregated proofs keyed by attestation data.
853+ Args:
854+ attestations: Individual attestations to aggregate and sign.
855+ aggregated_payloads: Aggregated proofs keyed by attestation data.
964856
965857 Returns:
966- -------
967- tuple[list[AggregatedAttestation], list[AggregatedSignatureProof]]
968858 Paired attestations and their corresponding proofs.
969859 """
970860 results : list [tuple [AggregatedAttestation , AggregatedSignatureProof ]] = []
0 commit comments