Skip to content

Commit 35bf38d

Browse files
Fix get committees size using the state (#9249)
* Fix getCommitteesSizeUsingTheState * fix meaning of optional current epoch also changed messages to debug as they're useless to users, which I had left previously but this will make more sense in debug. The test cases had to be updated to return an epoch to make the code exercised. Signed-off-by: Paul Harris <[email protected]> --------- Signed-off-by: Paul Harris <[email protected]> Co-authored-by: Paul Harris <[email protected]>
1 parent 9bc1bac commit 35bf38d

File tree

2 files changed

+44
-31
lines changed

2 files changed

+44
-31
lines changed

ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/attestation/AggregatingAttestationPool.java

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.apache.tuweni.bytes.Bytes32;
3535
import org.hyperledger.besu.plugin.services.MetricsSystem;
3636
import tech.pegasys.teku.ethereum.events.SlotEventsChannel;
37-
import tech.pegasys.teku.infrastructure.async.SafeFuture;
3837
import tech.pegasys.teku.infrastructure.metrics.SettableGauge;
3938
import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory;
4039
import tech.pegasys.teku.infrastructure.ssz.SszList;
@@ -173,42 +172,49 @@ private Optional<Int2IntMap> getCommitteesSizeUsingTheState(
173172
final AttestationData attestationData) {
174173
// we can use the first state of the epoch to get committees for an attestation
175174
final MiscHelpers miscHelpers = spec.atSlot(attestationData.getSlot()).miscHelpers();
176-
final UInt64 currentEpoch = miscHelpers.computeEpochAtSlot(attestationData.getSlot());
175+
final Optional<UInt64> maybeEpoch = recentChainData.getCurrentEpoch();
176+
// the only reason this can happen is we don't have a store yet.
177+
if (maybeEpoch.isEmpty()) {
178+
return Optional.empty();
179+
}
180+
final UInt64 currentEpoch = maybeEpoch.get();
177181
final UInt64 attestationEpoch = miscHelpers.computeEpochAtSlot(attestationData.getSlot());
178182

179183
LOG.debug("currentEpoch {}, attestationEpoch {}", currentEpoch, attestationEpoch);
180184
if (attestationEpoch.equals(currentEpoch)
181-
|| attestationEpoch.equals(currentEpoch.decrement())) {
182-
183-
final Optional<SafeFuture<BeaconState>> maybeFuture = recentChainData.getBestState();
184-
if (maybeFuture.isEmpty()) {
185-
return Optional.empty();
186-
} else {
187-
try {
188-
final BeaconState state = maybeFuture.get().getImmediately();
189-
return Optional.of(spec.getBeaconCommitteesSize(state, attestationData.getSlot()));
190-
} catch (IllegalStateException e) {
191-
LOG.info(
192-
"Couldn't retrieve state for committee calculation of slot {}",
193-
attestationData.getSlot());
194-
return Optional.empty();
195-
}
196-
}
185+
|| attestationEpoch.equals(currentEpoch.minusMinZero(1))) {
186+
187+
return recentChainData
188+
.getBestState()
189+
.flatMap(
190+
state -> {
191+
try {
192+
return Optional.of(
193+
spec.getBeaconCommitteesSize(
194+
state.getImmediately(), attestationData.getSlot()));
195+
} catch (IllegalStateException e) {
196+
LOG.debug(
197+
"Couldn't retrieve state for committee calculation of slot {}",
198+
attestationData.getSlot());
199+
return Optional.empty();
200+
}
201+
});
197202
}
198203

199204
// attestation is not from the current or previous epoch
200-
LOG.debug("State at slot {} needed", miscHelpers.computeStartSlotAtEpoch(attestationEpoch));
201-
final SafeFuture<Optional<BeaconState>> optionalFutureBeaconState =
202-
recentChainData.retrieveStateInEffectAtSlot(
203-
miscHelpers.computeStartSlotAtEpoch(attestationEpoch));
205+
// this is really an edge case because the current or previous epoch is at least 31 slots
206+
// and the attestation is only valid for 64 slots, so it may be epoch-2 but not beyond.
207+
final UInt64 attestationEpochStartSlot = miscHelpers.computeStartSlotAtEpoch(attestationEpoch);
208+
LOG.debug("State at slot {} needed", attestationEpochStartSlot);
204209
try {
205-
final Optional<BeaconState> maybeState = optionalFutureBeaconState.getImmediately();
206-
return maybeState.map(
207-
state -> spec.getBeaconCommitteesSize(state, attestationData.getSlot()));
208-
} catch (IllegalStateException e) {
209-
LOG.info(
210+
return recentChainData
211+
.retrieveStateInEffectAtSlot(attestationEpochStartSlot)
212+
.getImmediately()
213+
.map(state -> spec.getBeaconCommitteesSize(state, attestationData.getSlot()));
214+
} catch (final IllegalStateException e) {
215+
LOG.debug(
210216
"Couldn't retrieve state in effect at slot {} for committee calculation of slot {}",
211-
miscHelpers.computeStartSlotAtEpoch(attestationEpoch),
217+
attestationEpochStartSlot,
212218
attestationData.getSlot());
213219
return Optional.empty();
214220
}

ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/attestation/AggregatingAttestationPoolTest.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,11 @@ public void getSize_shouldIncludeAttestationsAdded() {
400400

401401
@TestTemplate
402402
public void getSize_shouldDecreaseWhenAttestationsRemoved() {
403-
final AttestationData attestationData = dataStructureUtil.randomAttestationData();
403+
final AttestationData attestationData = dataStructureUtil.randomAttestationData(ZERO);
404404
addAttestationFromValidators(attestationData, 1, 2, 3, 4);
405405
final Attestation attestationToRemove = addAttestationFromValidators(attestationData, 2, 5);
406+
407+
when(mockRecentChainData.getCurrentEpoch()).thenReturn(Optional.of(ZERO));
406408
aggregatingPool.onAttestationsIncludedInBlock(ZERO, List.of(attestationToRemove));
407409
assertThat(aggregatingPool.getSize()).isEqualTo(1);
408410
}
@@ -418,12 +420,14 @@ public void getSize_shouldNotIncrementWhenAttestationAlreadyExists() {
418420

419421
@TestTemplate
420422
public void getSize_shouldDecrementForAllRemovedAttestations() {
421-
final AttestationData attestationData = dataStructureUtil.randomAttestationData();
423+
final AttestationData attestationData = dataStructureUtil.randomAttestationData(ZERO);
422424
addAttestationFromValidators(attestationData, 1, 2, 3);
423425
addAttestationFromValidators(attestationData, 4, 5);
424426
assertThat(aggregatingPool.getSize()).isEqualTo(2);
425427
final Attestation attestationToRemove =
426428
addAttestationFromValidators(attestationData, 1, 2, 3, 4, 5);
429+
430+
when(mockRecentChainData.getCurrentEpoch()).thenReturn(Optional.of(ZERO));
427431
aggregatingPool.onAttestationsIncludedInBlock(ZERO, List.of(attestationToRemove));
428432
assertThat(aggregatingPool.getSize()).isEqualTo(0);
429433
}
@@ -441,7 +445,7 @@ public void getSize_shouldAddTheRightData() {
441445

442446
@TestTemplate
443447
public void getSize_shouldDecrementForAllRemovedAttestationsWhileKeepingOthers() {
444-
final AttestationData attestationData = dataStructureUtil.randomAttestationData();
448+
final AttestationData attestationData = dataStructureUtil.randomAttestationData(ZERO);
445449

446450
addAttestationFromValidators(attestationData, 1, 2, 3);
447451
addAttestationFromValidators(attestationData, 4, 5);
@@ -452,6 +456,7 @@ public void getSize_shouldDecrementForAllRemovedAttestationsWhileKeepingOthers()
452456
addAttestationFromValidators(attestationData, 1, 2, 3, 4, 5);
453457
assertThat(aggregatingPool.getSize()).isEqualTo(5);
454458

459+
when(mockRecentChainData.getCurrentEpoch()).thenReturn(Optional.of(ONE));
455460
aggregatingPool.onAttestationsIncludedInBlock(ZERO, List.of(attestationToRemove));
456461
assertThat(aggregatingPool.getSize()).isEqualTo(2);
457462
}
@@ -627,6 +632,7 @@ public void getAttestations_shouldReturnAttestationsForGivenSlotOnly() {
627632
@TestTemplate
628633
void onAttestationsIncludedInBlock_shouldNotAddAttestationsAlreadySeenInABlock() {
629634
final AttestationData attestationData = dataStructureUtil.randomAttestationData(ZERO);
635+
when(mockRecentChainData.getCurrentEpoch()).thenReturn(Optional.of(ZERO));
630636
// Included in block before we see any attestations with this data
631637
aggregatingPool.onAttestationsIncludedInBlock(
632638
ONE, List.of(createAttestation(attestationData, 1, 2, 3, 4)));
@@ -639,6 +645,7 @@ void onAttestationsIncludedInBlock_shouldNotAddAttestationsAlreadySeenInABlock()
639645
@TestTemplate
640646
void onAttestationsIncludedInBlock_shouldRemoveAttestationsWhenSeenInABlock() {
641647
final AttestationData attestationData = dataStructureUtil.randomAttestationData(ZERO);
648+
when(mockRecentChainData.getCurrentEpoch()).thenReturn(Optional.of(ZERO));
642649
addAttestationFromValidators(attestationData, 2, 3);
643650

644651
aggregatingPool.onAttestationsIncludedInBlock(

0 commit comments

Comments
 (0)