@@ -187,6 +187,13 @@ impl<E: EthSpec> CompactIndexedAttestation<E> {
187187 _ => ( ) ,
188188 }
189189 }
190+
191+ pub fn committee_index ( & self ) -> u64 {
192+ match self {
193+ CompactIndexedAttestation :: Base ( att) => att. index ,
194+ CompactIndexedAttestation :: Electra ( att) => att. committee_index ( ) ,
195+ }
196+ }
190197}
191198
192199impl < E : EthSpec > CompactIndexedAttestationBase < E > {
@@ -276,25 +283,34 @@ impl<E: EthSpec> AttestationMap<E> {
276283 let Some ( attestation_map) = self . checkpoint_map . get_mut ( & checkpoint_key) else {
277284 return ;
278285 } ;
279- for ( compact_attestation_data, compact_indexed_attestations) in
280- attestation_map. attestations . iter_mut ( )
281- {
286+ for ( _, compact_indexed_attestations) in attestation_map. attestations . iter_mut ( ) {
282287 let unaggregated_attestations = std:: mem:: take ( compact_indexed_attestations) ;
283- let mut aggregated_attestations = vec ! [ ] ;
288+ let mut aggregated_attestations: Vec < CompactIndexedAttestation < E > > = vec ! [ ] ;
284289
285290 // Aggregate the best attestations for each committee and leave the rest.
286- let mut best_attestations_by_committee = BTreeMap :: new ( ) ;
291+ let mut best_attestations_by_committee: BTreeMap < u64 , CompactIndexedAttestation < E > > =
292+ BTreeMap :: new ( ) ;
287293
288294 for committee_attestation in unaggregated_attestations {
289295 // TODO(electra)
290296 // compare to best attestations by committee
291297 // could probably use `.entry` here
292298 if let Some ( existing_attestation) =
293- best_attestations_by_committee. get_mut ( committee_attestation. committee_index ( ) )
299+ best_attestations_by_committee. get_mut ( & committee_attestation. committee_index ( ) )
294300 {
295301 // compare and swap, put the discarded one straight into
296302 // `aggregated_attestations` in case we have room to pack it without
297303 // cross-committee aggregation
304+ if existing_attestation. should_aggregate ( & committee_attestation) {
305+ existing_attestation. aggregate ( & committee_attestation) ;
306+
307+ best_attestations_by_committee. insert (
308+ committee_attestation. committee_index ( ) ,
309+ committee_attestation,
310+ ) ;
311+ } else {
312+ aggregated_attestations. push ( committee_attestation) ;
313+ }
298314 } else {
299315 best_attestations_by_committee. insert (
300316 committee_attestation. committee_index ( ) ,
@@ -305,11 +321,62 @@ impl<E: EthSpec> AttestationMap<E> {
305321
306322 // TODO(electra): aggregate all the best attestations by committee
307323 // (use btreemap sort order to get order by committee index)
324+ aggregated_attestations. extend ( Self :: compute_on_chain_aggregate (
325+ best_attestations_by_committee,
326+ ) ) ;
308327
309328 * compact_indexed_attestations = aggregated_attestations;
310329 }
311330 }
312331
332+ // TODO(electra) unwraps in this function should be cleaned up
333+ // also in general this could be a bit more elegant
334+ pub fn compute_on_chain_aggregate (
335+ mut attestations_by_committee : BTreeMap < u64 , CompactIndexedAttestation < E > > ,
336+ ) -> Vec < CompactIndexedAttestation < E > > {
337+ let mut aggregated_attestations = vec ! [ ] ;
338+ if let Some ( ( _, on_chain_aggregate) ) = attestations_by_committee. pop_first ( ) {
339+ match on_chain_aggregate {
340+ CompactIndexedAttestation :: Base ( a) => {
341+ aggregated_attestations. push ( CompactIndexedAttestation :: Base ( a) ) ;
342+ aggregated_attestations. extend (
343+ attestations_by_committee
344+ . values ( )
345+ . map ( |a| {
346+ CompactIndexedAttestation :: Base ( CompactIndexedAttestationBase {
347+ attesting_indices : a. attesting_indices ( ) . clone ( ) ,
348+ aggregation_bits : a. aggregation_bits_base ( ) . unwrap ( ) . clone ( ) ,
349+ signature : a. signature ( ) . clone ( ) ,
350+ index : * a. index ( ) ,
351+ } )
352+ } )
353+ . collect :: < Vec < CompactIndexedAttestation < E > > > ( ) ,
354+ ) ;
355+ }
356+ CompactIndexedAttestation :: Electra ( mut a) => {
357+ for ( _, attestation) in attestations_by_committee. iter_mut ( ) {
358+ let new_committee_bits = a
359+ . committee_bits
360+ . union ( attestation. committee_bits ( ) . unwrap ( ) ) ;
361+ a. aggregate ( attestation. as_electra ( ) . unwrap ( ) ) ;
362+
363+ a = CompactIndexedAttestationElectra {
364+ attesting_indices : a. attesting_indices . clone ( ) ,
365+ aggregation_bits : a. aggregation_bits . clone ( ) ,
366+ signature : a. signature . clone ( ) ,
367+ index : a. index ,
368+ committee_bits : new_committee_bits,
369+ } ;
370+ }
371+
372+ aggregated_attestations. push ( CompactIndexedAttestation :: Electra ( a) ) ;
373+ }
374+ }
375+ }
376+
377+ aggregated_attestations
378+ }
379+
313380 /// Iterate all attestations matching the given `checkpoint_key`.
314381 pub fn get_attestations < ' a > (
315382 & ' a self ,
0 commit comments