1
1
import { PublicKey } from "@chainsafe/blst" ;
2
2
import * as immutable from "immutable" ;
3
3
import { fromHexString } from "@chainsafe/ssz" ;
4
- import { BLSSignature , CommitteeIndex , Epoch , Slot , ValidatorIndex , phase0 , SyncPeriod } from "@lodestar/types" ;
4
+ import {
5
+ BLSSignature ,
6
+ CommitteeIndex ,
7
+ Epoch ,
8
+ Slot ,
9
+ ValidatorIndex ,
10
+ phase0 ,
11
+ SyncPeriod ,
12
+ allForks ,
13
+ electra ,
14
+ } from "@lodestar/types" ;
5
15
import { createBeaconConfig , BeaconConfig , ChainConfig } from "@lodestar/config" ;
6
16
import {
7
17
ATTESTATION_SUBNET_COUNT ,
@@ -651,15 +661,47 @@ export class EpochCache {
651
661
* Return the beacon committee at slot for index.
652
662
*/
653
663
getBeaconCommittee ( slot : Slot , index : CommitteeIndex ) : Uint32Array {
664
+ return this . getBeaconCommittees ( slot , [ index ] ) ;
665
+ }
666
+
667
+ /**
668
+ * Return a single Uint32Array representing concatted committees of indices
669
+ */
670
+ getBeaconCommittees ( slot : Slot , indices : CommitteeIndex [ ] ) : Uint32Array {
671
+ if ( indices . length === 0 ) {
672
+ throw new Error ( "Attempt to get committees without providing CommitteeIndex" ) ;
673
+ }
674
+
654
675
const slotCommittees = this . getShufflingAtSlot ( slot ) . committees [ slot % SLOTS_PER_EPOCH ] ;
655
- if ( index >= slotCommittees . length ) {
656
- throw new EpochCacheError ( {
657
- code : EpochCacheErrorCode . COMMITTEE_INDEX_OUT_OF_RANGE ,
658
- index,
659
- maxIndex : slotCommittees . length ,
660
- } ) ;
676
+ const committees = [ ] ;
677
+
678
+ for ( const index of indices ) {
679
+ if ( index >= slotCommittees . length ) {
680
+ throw new EpochCacheError ( {
681
+ code : EpochCacheErrorCode . COMMITTEE_INDEX_OUT_OF_RANGE ,
682
+ index,
683
+ maxIndex : slotCommittees . length ,
684
+ } ) ;
685
+ }
686
+ committees . push ( slotCommittees [ index ] ) ;
687
+ }
688
+
689
+ // Early return if only one index
690
+ if ( committees . length === 1 ) {
691
+ return committees [ 0 ] ;
692
+ }
693
+
694
+ // Create a new Uint32Array to flatten `committees`
695
+ const totalLength = committees . reduce ( ( acc , curr ) => acc + curr . length , 0 ) ;
696
+ const result = new Uint32Array ( totalLength ) ;
697
+
698
+ let offset = 0 ;
699
+ for ( const committee of committees ) {
700
+ result . set ( committee , offset ) ;
701
+ offset += committee . length ;
661
702
}
662
- return slotCommittees [ index ] ;
703
+
704
+ return result ;
663
705
}
664
706
665
707
getCommitteeCountPerSlot ( epoch : Epoch ) : number {
@@ -745,10 +787,9 @@ export class EpochCache {
745
787
/**
746
788
* Return the indexed attestation corresponding to ``attestation``.
747
789
*/
748
- getIndexedAttestation ( attestation : phase0 . Attestation ) : phase0 . IndexedAttestation {
749
- const { aggregationBits, data} = attestation ;
750
- const committeeIndices = this . getBeaconCommittee ( data . slot , data . index ) ;
751
- const attestingIndices = aggregationBits . intersectValues ( committeeIndices ) ;
790
+ getIndexedAttestation ( fork : ForkSeq , attestation : allForks . Attestation ) : allForks . IndexedAttestation {
791
+ const { data} = attestation ;
792
+ const attestingIndices = this . getAttestingIndices ( fork , attestation ) ;
752
793
753
794
// sort in-place
754
795
attestingIndices . sort ( ( a , b ) => a - b ) ;
@@ -759,6 +800,31 @@ export class EpochCache {
759
800
} ;
760
801
}
761
802
803
+ /**
804
+ * Return indices of validators who attestested in `attestation`
805
+ */
806
+ getAttestingIndices ( fork : ForkSeq , attestation : allForks . Attestation ) : number [ ] {
807
+ if ( fork < ForkSeq . electra ) {
808
+ const { aggregationBits, data} = attestation ;
809
+ const validatorIndices = this . getBeaconCommittee ( data . slot , data . index ) ;
810
+
811
+ return aggregationBits . intersectValues ( validatorIndices ) ;
812
+ } else {
813
+ const { aggregationBits, committeeBits, data} = attestation as electra . Attestation ;
814
+
815
+ // There is a naming conflict on the term `committeeIndices`
816
+ // In Lodestar it usually means a list of validator indices of participants in a committee
817
+ // In the spec it means a list of committee indices according to committeeBits
818
+ // This `committeeIndices` refers to the latter
819
+ // TODO Electra: resolve the naming conflicts
820
+ const committeeIndices = committeeBits . getTrueBitIndexes ( ) ;
821
+
822
+ const validatorIndices = this . getBeaconCommittees ( data . slot , committeeIndices ) ;
823
+
824
+ return aggregationBits . intersectValues ( validatorIndices ) ;
825
+ }
826
+ }
827
+
762
828
getCommitteeAssignments (
763
829
epoch : Epoch ,
764
830
requestedValidatorIndices : ValidatorIndex [ ]
0 commit comments