Skip to content

Commit

Permalink
handle validator statuses update
Browse files Browse the repository at this point in the history
  • Loading branch information
mehdi-aouadi committed Jan 30, 2024
1 parent 8c1d9a2 commit 91bf22a
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@

package tech.pegasys.teku.validator.api;

import java.util.Map;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
Expand Down Expand Up @@ -41,4 +44,7 @@ void onHeadUpdate(
void onAttesterSlashing(AttesterSlashing attesterSlashing);

void onProposerSlashing(ProposerSlashing proposerSlashing);

void onUpdatedValidatorStatuses(
Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses, boolean possibleMissingEvents);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
Expand Down Expand Up @@ -51,6 +54,11 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

@Override
protected Bytes32 getExpectedDependentRoot(
final Bytes32 headBlockRoot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
Expand Down Expand Up @@ -100,6 +101,11 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

private boolean isThirdSlotOfEpoch(final UInt64 slot) {
return slot.mod(spec.getSlotsPerEpoch(slot)).equals(UInt64.valueOf(2));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Map;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
Expand Down Expand Up @@ -48,6 +51,11 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

@Override
protected Bytes32 getExpectedDependentRoot(
final Bytes32 headBlockRoot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ public void onAttesterSlashing(AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

@Override
public void subscribeValidatorStatusesUpdates(final ValidatorStatusSubscriber subscriber) {
validatorStatusSubscribers.subscribe(subscriber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@

package tech.pegasys.teku.validator.client;

import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.constants.NetworkConstants;
Expand Down Expand Up @@ -192,6 +195,11 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

private class SyncCommitteePeriod {
private Optional<PendingDuties> duties = Optional.empty();
private final UInt64 periodStartEpoch;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,14 +568,16 @@ protected SafeFuture<?> doStart() {
})
.thenCompose(
__ -> {
eventChannels.subscribe(
ValidatorTimingChannel.class,
final ValidatorTimingActions validatorTimingActions =
new ValidatorTimingActions(
validatorIndexProvider,
validatorTimingChannels,
spec,
metricsSystem,
maybeValidatorSlashedAction));
maybeValidatorSlashedAction);
eventChannels.subscribe(ValidatorTimingChannel.class, validatorTimingActions);
validatorStatusProvider.subscribeValidatorStatusesUpdates(
validatorTimingActions::onUpdatedValidatorStatuses);
validatorStatusProvider.start().ifExceptionGetsHereRaiseABug();
return beaconNodeApi.subscribeToEvents();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.jetbrains.annotations.NotNull;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.metrics.SettableGauge;
import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory;
Expand Down Expand Up @@ -133,4 +136,31 @@ public void onProposerSlashing(final ProposerSlashing proposerSlashing) {
.ifPresent(slashedPubKey -> maybeValidatorSlashedAction.get().perform(slashedPubKey));
});
}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {
delegates.forEach(
delegates ->
delegates.onUpdatedValidatorStatuses(newValidatorStatuses, possibleMissingEvents));
maybeValidatorSlashedAction.ifPresent(
validatorSlashedAction ->
maybeValidatorSlashedAction
.get()
.perform(getSlashedOwnedValidatorsPubKeys(newValidatorStatuses)));
}

@NotNull
private List<BLSPublicKey> getSlashedOwnedValidatorsPubKeys(
Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses) {
return newValidatorStatuses.entrySet().stream()
.filter(
validatorStatusEntry ->
validatorStatusEntry.getValue().equals(ValidatorStatus.exited_slashed)
|| validatorStatusEntry.getValue().equals(ValidatorStatus.active_slashed))
.map(Map.Entry::getKey)
.filter(validatorIndexProvider::containsPublicKey)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@

package tech.pegasys.teku.validator.client.duties.synccommittee;

import java.util.Map;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing;
Expand Down Expand Up @@ -66,4 +69,9 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}

@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand All @@ -28,6 +29,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.ethereum.signingrecord.ValidatorSigningRecord;
import tech.pegasys.teku.infrastructure.async.AsyncRunner;
import tech.pegasys.teku.infrastructure.logging.ValidatorLogger;
Expand Down Expand Up @@ -193,4 +196,9 @@ public void onAttesterSlashing(final AttesterSlashing attesterSlashing) {}

@Override
public void onProposerSlashing(final ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.logging.StatusLogger;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
Expand Down Expand Up @@ -53,7 +56,7 @@ public class ValidatorTimingActionsTest {
Optional.of(new SlashedValidatorAlert(statusLogger));

@Test
public void shouldPrintAlertForSlashedValidators_AttesterSlashing() {
public void shouldTriggerSlashingActionForSlashedValidators_AttesterSlashing() {
final ValidatorTimingActions validatorTimingActions =
new ValidatorTimingActions(
validatorIndexProvider, delegates, spec, metricsSystem, maybeSlashedValidatorAction);
Expand All @@ -78,7 +81,7 @@ public void shouldPrintAlertForSlashedValidators_AttesterSlashing() {
}

@Test
public void shouldPrintAlertForSlashedValidators_ProposerSlashing() {
public void shouldTriggerSlashingActionForSlashedValidators_ProposerSlashing() {
final ValidatorTimingActions validatorTimingActions =
new ValidatorTimingActions(
validatorIndexProvider, delegates, spec, metricsSystem, maybeSlashedValidatorAction);
Expand Down Expand Up @@ -149,4 +152,51 @@ public void shouldNotTriggerValidatorSlashingActionWhenNotEnabled_ProposerSlashi
verifyNoInteractions(validatorIndexProvider);
verifyNoInteractions(statusLogger);
}

@Test
public void shouldTriggerSlashingActionForSlashedValidators_ValidatorStatusesUpdate() {
final ValidatorTimingActions validatorTimingActions =
new ValidatorTimingActions(
validatorIndexProvider, delegates, spec, metricsSystem, maybeSlashedValidatorAction);
final BLSPublicKey key1 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key2 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key3 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key4 = dataStructureUtil.randomPublicKey();
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses =
Map.ofEntries(
Map.entry(key1, ValidatorStatus.active_slashed),
Map.entry(key2, ValidatorStatus.exited_slashed),
Map.entry(key3, ValidatorStatus.active_ongoing),
Map.entry(key4, ValidatorStatus.exited_slashed));
when(validatorIndexProvider.containsPublicKey(key1)).thenReturn(true);
when(validatorIndexProvider.containsPublicKey(key2)).thenReturn(true);
when(validatorIndexProvider.containsPublicKey(key4)).thenReturn(false);
validatorTimingActions.onUpdatedValidatorStatuses(newValidatorStatuses, true);
verify(delegate).onUpdatedValidatorStatuses(newValidatorStatuses, true);
verify(validatorIndexProvider).containsPublicKey(key1);
verify(validatorIndexProvider).containsPublicKey(key2);
verify(validatorIndexProvider).containsPublicKey(key4);
verifyNoMoreInteractions(validatorIndexProvider);
verify(statusLogger).validatorSlashedAlert(Set.of(key1.toHexString(), key2.toHexString()));
}

@Test
public void shouldNotTriggerSlashingActionForSlashedValidators_ValidatorStatusesUpdate() {
final ValidatorTimingActions validatorTimingActions =
new ValidatorTimingActions(
validatorIndexProvider, delegates, spec, metricsSystem, Optional.empty());
final BLSPublicKey key1 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key2 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key3 = dataStructureUtil.randomPublicKey();
final BLSPublicKey key4 = dataStructureUtil.randomPublicKey();
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses =
Map.ofEntries(
Map.entry(key1, ValidatorStatus.active_slashed),
Map.entry(key2, ValidatorStatus.exited_slashed),
Map.entry(key3, ValidatorStatus.active_ongoing),
Map.entry(key4, ValidatorStatus.exited_slashed));
validatorTimingActions.onUpdatedValidatorStatuses(newValidatorStatuses, true);
verifyNoInteractions(validatorIndexProvider);
verifyNoInteractions(statusLogger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.logging.ValidatorLogger;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
Expand Down Expand Up @@ -118,6 +120,11 @@ public void onAttesterSlashing(AttesterSlashing attesterSlashing) {}
@Override
public void onProposerSlashing(ProposerSlashing proposerSlashing) {}

@Override
public void onUpdatedValidatorStatuses(
final Map<BLSPublicKey, ValidatorStatus> newValidatorStatuses,
final boolean possibleMissingEvents) {}

private SafeFuture<Void> performReadinessCheckAgainstAllNodes() {
// no readiness check needed when no failovers are configured
if (failoverBeaconNodeApis.isEmpty()) {
Expand Down

0 comments on commit 91bf22a

Please sign in to comment.