Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create EphemerySlotValidationService and test #8759

Merged
merged 11 commits into from
Oct 31, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult;
import tech.pegasys.teku.spec.logic.common.util.BlockRewardCalculatorUtil;
import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.teku.statetransition.EpochCachePrimer;
import tech.pegasys.teku.statetransition.LocalOperationAcceptedFilter;
import tech.pegasys.teku.statetransition.MappedOperationPool;
Expand Down Expand Up @@ -219,6 +220,7 @@
public class BeaconChainController extends Service implements BeaconChainControllerFacade {

private static final Logger LOG = LogManager.getLogger();
private final EphemerySlotValidationService ephemerySlotValidationService;

protected static final String KEY_VALUE_STORE_SUBDIRECTORY = "kvstore";

Expand Down Expand Up @@ -335,6 +337,7 @@ public BeaconChainController(
"future_items_size",
"Current number of items held for future slots, labelled by type",
"type");
this.ephemerySlotValidationService = new EphemerySlotValidationService();
}

@Override
Expand Down Expand Up @@ -364,6 +367,12 @@ protected void startServices() {
blobSidecar ->
recentBlobSidecarsFetcher.cancelRecentBlobSidecarRequest(
new BlobIdentifier(blobSidecar.getBlockRoot(), blobSidecar.getIndex())));

final Optional<Eth2Network> network = beaconConfig.eth2NetworkConfig().getEth2Network();
if (network.isPresent() && network.get() == Eth2Network.EPHEMERY) {
LOG.debug("BeaconChainController: subscribing to slot events");
eventChannels.subscribe(SlotEventsChannel.class, ephemerySlotValidationService);
}
SafeFuture.allOfFailFast(
attestationManager.start(),
p2pNetwork.start(),
Expand Down Expand Up @@ -401,6 +410,7 @@ protected SafeFuture<?> doStop() {
attestationManager.stop(),
p2pNetwork.stop(),
timerService.stop(),
ephemerySlotValidationService.doStop(),
SafeFuture.fromRunnable(
() -> terminalPowBlockMonitor.ifPresent(TerminalPowBlockMonitor::stop)))
.thenRun(forkChoiceExecutor::stop);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Consensys Software Inc., 2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.services.beaconchain;

public class EphemeryLifecycleException extends RuntimeException {
public EphemeryLifecycleException(final String format) {
super(format);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Consensys Software Inc., 2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.services.beaconchain;

import static tech.pegasys.teku.networks.EphemeryNetwork.MAX_EPHEMERY_SLOT;

import tech.pegasys.teku.ethereum.events.SlotEventsChannel;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.service.serviceutils.Service;

public class EphemerySlotValidationService extends Service implements SlotEventsChannel {

@Override
public void onSlot(final UInt64 slot) {
if (slot.isGreaterThan(MAX_EPHEMERY_SLOT)) {
throw new EphemeryLifecycleException(
String.format(
"Slot %s exceeds maximum allowed slot %s for ephemery network",
slot, MAX_EPHEMERY_SLOT));
}
}

@Override
protected SafeFuture<?> doStart() {
return SafeFuture.COMPLETE;
}

@Override
protected SafeFuture<?> doStop() {
return SafeFuture.COMPLETE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright Consensys Software Inc., 2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.services.beaconchain;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static tech.pegasys.teku.networks.EphemeryNetwork.MAX_EPHEMERY_SLOT;

import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.networks.Eth2Network;

class EphemerySlotValidationServiceTest {
private EphemerySlotValidationService ephemerySlotValidationService;

@BeforeEach
void setUp() {
ephemerySlotValidationService = new EphemerySlotValidationService();
}

@Test
public void onSlot_shouldNotThrow_whenSlotIsValid() {
ephemerySlotValidationService.onSlot(UInt64.valueOf(MAX_EPHEMERY_SLOT));
}

@Test
public void onSlot_shouldThrowException_whenSlotExceedsMaxEphemerySlot_forEphemeryNetwork() {
final Eth2Network network = Eth2Network.EPHEMERY;
final Optional<Eth2Network> ephemeryNetwork = Optional.of(network);
final UInt64 invalidSlot = UInt64.valueOf(MAX_EPHEMERY_SLOT + 1);

assertThat(ephemeryNetwork).contains(Eth2Network.EPHEMERY);
assertThatThrownBy(() -> ephemerySlotValidationService.onSlot(invalidSlot))
.isInstanceOf(EphemeryLifecycleException.class)
.hasMessageContaining(
String.format(
"Slot %s exceeds maximum allowed slot %s for ephemery network",
invalidSlot, MAX_EPHEMERY_SLOT));
}

@Test
void shouldCompleteWhenServiceStartsAndStops() {
final SafeFuture<?> startFuture = ephemerySlotValidationService.doStart();
assertTrue(startFuture.isDone());
final SafeFuture<?> stopFuture = ephemerySlotValidationService.doStop();
assertTrue(stopFuture.isDone());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import tech.pegasys.teku.infrastructure.exceptions.ExceptionUtil;
import tech.pegasys.teku.infrastructure.exceptions.FatalServiceFailureException;
import tech.pegasys.teku.infrastructure.logging.StatusLogger;
import tech.pegasys.teku.services.beaconchain.EphemeryLifecycleException;
import tech.pegasys.teku.storage.server.DatabaseStorageException;
import tech.pegasys.teku.storage.server.ShuttingDownException;

Expand Down Expand Up @@ -85,6 +86,9 @@ private void handleException(final Throwable exception, final String subscriberD
} else if (exception instanceof OutOfMemoryError) {
statusLog.fatalError(subscriberDescription, exception);
System.exit(ERROR_EXIT_CODE);
} else if (exception instanceof EphemeryLifecycleException) {
statusLog.fatalError(subscriberDescription, exception);
System.exit(ERROR_EXIT_CODE);
} else if (exception instanceof ShuttingDownException) {
LOG.debug("Shutting down", exception);
} else if (isExpectedNettyError(exception)) {
Expand Down