77
88from __future__ import annotations
99
10- from typing import ClassVar , Self
10+ from typing import ClassVar , Mapping , Self
1111
1212from pydantic import model_validator
1313
3838from lean_spec .subspecs .containers .validator import ValidatorIndex
3939from lean_spec .subspecs .forkchoice import Store
4040from lean_spec .subspecs .ssz import hash_tree_root
41- from lean_spec .subspecs .xmss .aggregation import SignatureKey
4241from lean_spec .subspecs .xmss .containers import Signature
4342from lean_spec .types import Bytes32 , Uint64
4443
@@ -381,20 +380,23 @@ def _build_block_from_spec(
381380 #
382381 # Attestations vote for blocks and influence fork choice weight.
383382 # The spec may include attestations to include in this block.
384- attestations , attestation_signatures , valid_signature_keys = (
385- self ._build_attestations_from_spec (
386- spec , store , block_registry , parent_root , key_manager
387- )
383+ (
384+ attestations ,
385+ attestation_signatures ,
386+ valid_attestations ,
387+ ) = self ._build_attestations_from_spec (
388+ spec , store , block_registry , parent_root , key_manager
388389 )
389390
390- # Merge per- attestation signatures into the Store's gossip signature cache.
391- # Required so the Store can aggregate committee signatures later when building payloads .
391+ # Merge valid attestation signatures into the Store's gossip cache.
392+ # Only attestations with valid (non-dummy) signatures are merged .
392393 working_store = store
393- for attestation in attestations :
394- sig_key = SignatureKey (attestation .validator_id , attestation .data .data_root_bytes ())
395- if sig_key not in valid_signature_keys :
396- continue
397- if (signature := attestation_signatures .get (sig_key )) is None :
394+ for attestation in valid_attestations :
395+ sigs_for_data = attestation_signatures .get (attestation .data )
396+ if (
397+ sigs_for_data is None
398+ or (signature := sigs_for_data .get (attestation .validator_id )) is None
399+ ):
398400 continue
399401 working_store = working_store .on_gossip_attestation (
400402 SignedAttestation (
@@ -564,7 +566,11 @@ def _build_attestations_from_spec(
564566 block_registry : dict [str , Block ],
565567 parent_root : Bytes32 ,
566568 key_manager : XmssKeyManager ,
567- ) -> tuple [list [Attestation ], dict [SignatureKey , Signature ], set [SignatureKey ]]:
569+ ) -> tuple [
570+ list [Attestation ],
571+ Mapping [AttestationData , Mapping [ValidatorIndex , Signature ]],
572+ set [Attestation ],
573+ ]:
568574 """
569575 Build attestations and signatures from block specification.
570576
@@ -580,16 +586,16 @@ def _build_attestations_from_spec(
580586 key_manager: Key manager for signing.
581587
582588 Returns:
583- Tuple of (attestations list, signature lookup dict , valid signature keys ).
589+ Tuple of (attestations list, signature lookup by data , valid attestations ).
584590 """
585591 # No attestations specified means empty block body.
586592 if spec .attestations is None :
587593 return [], {}, set ()
588594
589595 parent_state = store .states [parent_root ]
590596 attestations = []
591- signature_lookup : dict [ SignatureKey , Signature ] = {}
592- valid_signature_keys : set [SignatureKey ] = set ()
597+ signature_lookup : Mapping [ AttestationData , Mapping [ ValidatorIndex , Signature ] ] = {}
598+ valid_attestations : set [Attestation ] = set ()
593599
594600 for aggregated_spec in spec .attestations :
595601 # Build attestation data once.
@@ -614,19 +620,19 @@ def _build_attestations_from_spec(
614620 validator_id ,
615621 attestation_data ,
616622 )
623+ valid_attestations .add (attestation )
617624 else :
618625 # Dummy signature for testing invalid signature handling.
619626 # The Store should reject attestations with bad signatures.
620627 signature = create_dummy_signature ()
621628
622- # Index signature by validator and data root.
623- # This enables lookup during signature aggregation.
624- sig_key = SignatureKey (validator_id , attestation_data .data_root_bytes ())
625- signature_lookup [sig_key ] = signature
626- if aggregated_spec .valid_signature :
627- valid_signature_keys .add (sig_key )
629+ # Index signature by attestation data and validator ID.
630+ signature_lookup .setdefault (attestation_data , {}).setdefault (
631+ validator_id ,
632+ signature ,
633+ )
628634
629- return attestations , signature_lookup , valid_signature_keys
635+ return attestations , signature_lookup , valid_attestations
630636
631637 def _build_attestation_data_from_spec (
632638 self ,
0 commit comments