@@ -556,7 +556,7 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
556556 { :ok , IndexedAttestation . t ( ) } | { :error , String . t ( ) }
557557 def get_indexed_attestation ( % BeaconState { } = state , attestation ) do
558558 with { :ok , indices } <-
559- get_attesting_indices ( state , attestation . data , attestation . aggregation_bits ) do
559+ get_attesting_indices ( state , attestation ) do
560560 % IndexedAttestation {
561561 attesting_indices: Enum . sort ( indices ) ,
562562 data: attestation . data ,
@@ -585,16 +585,34 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
585585 that slot) and then filters the ones that actually participated. It returns an unordered MapSet,
586586 which is useful for checking inclusion, but should be ordered if used to validate an attestation.
587587 """
588- @ spec get_attesting_indices ( BeaconState . t ( ) , Types.AttestationData . t ( ) , Types . bitlist ( ) ) ::
588+ @ spec get_attesting_indices ( BeaconState . t ( ) , Types.Attestation . t ( ) ) ::
589589 { :ok , MapSet . t ( ) } | { :error , String . t ( ) }
590- def get_attesting_indices ( % BeaconState { } = state , data , bits ) do
591- with { :ok , committee } <- get_beacon_committee ( state , data . slot , data . index ) do
592- committee
593- |> Stream . with_index ( )
594- |> Stream . filter ( fn { _value , index } -> participated? ( bits , index ) end )
595- |> Stream . map ( fn { value , _index } -> value end )
596- |> MapSet . new ( )
597- |> then ( & { :ok , & 1 } )
590+ def get_attesting_indices ( % BeaconState { } = state , % Attestation {
591+ data: data ,
592+ aggregation_bits: aggregation_bits ,
593+ committee_bits: committee_bits
594+ } ) do
595+ committee_bits
596+ |> get_committee_indices ( )
597+ |> Enum . reduce_while ( { MapSet . new ( ) , 0 } , fn committee_index , { attesters , offset } ->
598+ case get_beacon_committee ( state , data . slot , committee_index ) do
599+ { :ok , committee } ->
600+ committee_attesters =
601+ committee
602+ |> Stream . with_index ( offset )
603+ |> Stream . filter ( fn { _validator , pos } -> participated? ( aggregation_bits , pos ) end )
604+ |> Stream . map ( fn { validator , _ } -> validator end )
605+ |> MapSet . new ( )
606+
607+ { :cont , { MapSet . union ( attesters , committee_attesters ) , offset + length ( committee ) } }
608+
609+ error ->
610+ { :halt , error }
611+ end
612+ end )
613+ |> case do
614+ { :error , error } -> { :error , error }
615+ { attesters , _offset } -> { :ok , attesters }
598616 end
599617 end
600618
@@ -629,4 +647,11 @@ defmodule LambdaEthereumConsensus.StateTransition.Accessors do
629647
630648 max ( ChainSpec . get ( "EFFECTIVE_BALANCE_INCREMENT" ) , total_balance )
631649 end
650+
651+ @ spec get_committee_indices ( Types . bitvector ( ) ) :: Enumerable . t ( Types . commitee_index ( ) )
652+ def get_committee_indices ( committee_bits ) do
653+ bitlist = committee_bits |> :binary . bin_to_list ( ) |> Enum . reverse ( )
654+
655+ for { bit , index } <- Enum . with_index ( bitlist ) , bit == 1 , do: index
656+ end
632657end
0 commit comments