Skip to content

Commit

Permalink
refactor attestations filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdi-aouadi committed Jul 24, 2024
1 parent c797ec0 commit f375c94
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 9 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

### Additions and Improvements
- Added a state pruner that can limit the number of finalized states stored when running an archive node.

- Updated bootnodes for Sepolia network.
- Implemented [GetBlockAttestationV2](https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getBlockAttestationsV2) (adding support for Electra attestations)
- Implemented [GetAttestationsV2](https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getPoolAttestationsV2) (adding support for Electra attestations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
Expand Down Expand Up @@ -273,32 +275,50 @@ public synchronized List<Attestation> getAttestations(
final Predicate<Map.Entry<UInt64, Set<Bytes>>> filterForSlot =
(entry) -> maybeSlot.map(slot -> entry.getKey().equals(slot)).orElse(true);

final Predicate<MatchingDataAttestationGroup> filterForCommitteeIndex =
(group) ->
maybeCommitteeIndex
.map(index -> group.getAttestationData().getIndex().equals(index))
.orElse(true);
final UInt64 slot = maybeSlot.orElse(recentChainData.getCurrentSlot().orElse(UInt64.ZERO));
final SchemaDefinitions schemaDefinitions = spec.atSlot(slot).getSchemaDefinitions();

final boolean requestRequiresAttestationWithCommitteeBits =
schemaDefinitions.getAttestationSchema().requiresCommitteeBits();

// Committee index filter predicate is used for pre Electra attestations only (the filter is
// applied to the index at the attestation data level)
// Post Electra the index is always set to 0 at the attestation data level (the filter
// is rather applied to the committee bits)
final Predicate<MatchingDataAttestationGroup> filterForCommitteeIndex =
(group) ->
requestRequiresAttestationWithCommitteeBits
|| maybeCommitteeIndex
.map(index -> group.getAttestationData().getIndex().equals(index))
.orElse(true);

return dataHashBySlot.descendingMap().entrySet().stream()
.filter(filterForSlot)
.map(Map.Entry::getValue)
.flatMap(Collection::stream)
.map(attestationGroupByDataHash::get)
.filter(Objects::nonNull)
.filter(filterForCommitteeIndex)
.flatMap(MatchingDataAttestationGroup::stream)
.flatMap(
streamMatchingAttestations(
maybeCommitteeIndex, requestRequiresAttestationWithCommitteeBits))
.map(ValidatableAttestation::getAttestation)
.filter(
attestation ->
attestation.requiresCommitteeBits() == requestRequiresAttestationWithCommitteeBits)
.toList();
}

private Function<MatchingDataAttestationGroup, Stream<ValidatableAttestation>>
streamMatchingAttestations(
final Optional<UInt64> maybeCommitteeIndex,
final boolean requestRequiresAttestationWithCommitteeBits) {
return matchingDataAttestationGroup ->
requestRequiresAttestationWithCommitteeBits
? matchingDataAttestationGroup.stream(maybeCommitteeIndex)
: matchingDataAttestationGroup.stream();
}

private boolean isValid(
final BeaconState stateAtBlockSlot, final AttestationData attestationData) {
return spec.validateAttestation(stateAtBlockSlot, attestationData).isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,10 @@ public void getAttestations_shouldReturnAllAttestations() {
}

@TestTemplate
public void getAttestations_shouldReturnAttestationsForGivenCommitteeIndexOnly() {
public void getAttestations_shouldReturnAttestationsForGivenCommitteeIndexOnly_PreElectra() {
assumeThat(specMilestone).isLessThan(ELECTRA);
// Pre Electra the committee index filter is applied to the index set at the attestation data
// level
final AttestationData attestationData1 = dataStructureUtil.randomAttestationData();
final AttestationData attestationData2 =
new AttestationData(
Expand All @@ -531,14 +534,28 @@ public void getAttestations_shouldReturnAttestationsForGivenCommitteeIndexOnly()
attestationData1.getBeaconBlockRoot(),
attestationData1.getSource(),
attestationData1.getTarget());
Attestation attestation1 = addAttestationFromValidators(attestationData1, 1, 2, 3);
final Attestation attestation1 = addAttestationFromValidators(attestationData1, 1, 2, 3);
addAttestationFromValidators(attestationData2, 4, 5, 6);
assertThat(
aggregatingPool.getAttestations(
Optional.empty(), Optional.of(attestationData1.getIndex())))
.containsExactly(attestation1);
}

@TestTemplate
public void getAttestations_shouldReturnAttestationsForGivenCommitteeIndexOnly_PostElectra() {
assumeThat(specMilestone).isGreaterThanOrEqualTo(ELECTRA);
// Post Electra the committee index filter is applied to the committee bits
final AttestationData attestationData1 = dataStructureUtil.randomAttestationData();
final AttestationData attestationData2 = dataStructureUtil.randomAttestationData();
final Attestation attestation1 = addAttestationFromValidators(attestationData1, 1, 2, 3);
final Optional<UInt64> committeeIndexFilter = committeeIndex;
committeeIndex = Optional.of(committeeIndex.get().plus(1));
addAttestationFromValidators(attestationData2, 4, 5, 6);
assertThat(aggregatingPool.getAttestations(Optional.empty(), committeeIndexFilter))
.containsExactly(attestation1);
}

@TestTemplate
public void getAttestations_shouldReturnAttestationsForGivenSlotOnly() {
final AttestationData attestationData1 = dataStructureUtil.randomAttestationData();
Expand Down

0 comments on commit f375c94

Please sign in to comment.