diff --git a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/DepositProvider.java b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/DepositProvider.java index 45dc0751690..f022cdc5455 100644 --- a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/DepositProvider.java +++ b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/DepositProvider.java @@ -171,7 +171,7 @@ public void onEth1Block( } @Override - public void onMinGenesisTimeBlock(MinGenesisTimeBlockEvent event) {} + public void onMinGenesisTimeBlock(final MinGenesisTimeBlockEvent event) {} @Override public void onSlot(final UInt64 slot) { @@ -187,6 +187,12 @@ public void onSlot(final UInt64 slot) { .get() .thenAccept( state -> { + if (spec.isFormerDepositMechanismDisabled(state)) { + // No need to check eth1 deposits are available if former deposit mechanism has been + // disabled + return; + } + final UInt64 eth1DepositCount = state.getEth1Data().getDepositCount(); final UInt64 lastAvailableDepositIndex = diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java index 896a1e42729..b39cd36cb7b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java @@ -940,6 +940,11 @@ public Optional computeFirstSlotWithBlobSupport() { .map(this::computeStartSlotAtEpoch); } + // Electra Utils + public boolean isFormerDepositMechanismDisabled(final BeaconState state) { + return atState(state).miscHelpers().isFormerDepositMechanismDisabled(state); + } + // Deneb private helpers private Optional getSpecConfigDeneb() { final SpecMilestone highestSupportedMilestone = diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java index 364da862ea6..ace2a21ac51 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java @@ -374,6 +374,10 @@ public UInt64 getMaxRequestBlocks() { return UInt64.valueOf(specConfig.getNetworkingConfig().getMaxRequestBlocks()); } + public boolean isFormerDepositMechanismDisabled(final BeaconState state) { + return false; + } + public Optional toVersionDeneb() { return Optional.empty(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/SpecLogicElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/SpecLogicElectra.java index 12ec358b02b..bd8f8ee8e39 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/SpecLogicElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/SpecLogicElectra.java @@ -43,6 +43,7 @@ import tech.pegasys.teku.spec.logic.versions.deneb.util.ForkChoiceUtilDeneb; import tech.pegasys.teku.spec.logic.versions.electra.block.BlockProcessorElectra; import tech.pegasys.teku.spec.logic.versions.electra.forktransition.ElectraStateUpgrade; +import tech.pegasys.teku.spec.logic.versions.electra.helpers.MiscHelpersElectra; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; public class SpecLogicElectra extends AbstractSpecLogic { @@ -93,8 +94,8 @@ public static SpecLogicElectra create( final SpecConfigElectra config, final SchemaDefinitionsElectra schemaDefinitions) { // Helpers final Predicates predicates = new Predicates(config); - final MiscHelpersDeneb miscHelpers = - new MiscHelpersDeneb(config, predicates, schemaDefinitions); + final MiscHelpersElectra miscHelpers = + new MiscHelpersElectra(config, predicates, schemaDefinitions); final BeaconStateAccessorsDeneb beaconStateAccessors = new BeaconStateAccessorsDeneb(config, predicates, miscHelpers); final BeaconStateMutatorsBellatrix beaconStateMutators = diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectra.java new file mode 100644 index 00000000000..fe3f37b2edf --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectra.java @@ -0,0 +1,39 @@ +/* + * 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.spec.logic.versions.electra.helpers; + +import tech.pegasys.teku.spec.config.SpecConfigElectra; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.BeaconStateElectra; +import tech.pegasys.teku.spec.logic.common.helpers.Predicates; +import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; + +public class MiscHelpersElectra extends MiscHelpersDeneb { + + public MiscHelpersElectra( + final SpecConfigElectra specConfig, + final Predicates predicates, + final SchemaDefinitionsElectra schemaDefinitions) { + super(specConfig, predicates, schemaDefinitions); + } + + @Override + public boolean isFormerDepositMechanismDisabled(final BeaconState state) { + return state + .getEth1DepositIndex() + .plus(1) + .equals(BeaconStateElectra.required(state).getDepositReceiptsStartIndex()); + } +} diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java new file mode 100644 index 00000000000..706b8f0dce4 --- /dev/null +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java @@ -0,0 +1,75 @@ +/* + * 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.spec.logic.versions.electra.helpers; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.TestSpecFactory; +import tech.pegasys.teku.spec.config.SpecConfigElectra; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.BeaconStateElectra; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.MutableBeaconStateElectra; +import tech.pegasys.teku.spec.logic.common.helpers.Predicates; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; +import tech.pegasys.teku.spec.util.DataStructureUtil; + +public class MiscHelpersElectraTest { + + private final Spec spec = TestSpecFactory.createMinimalElectra(); + private final Predicates predicates = new Predicates(spec.getGenesisSpecConfig()); + private final SchemaDefinitionsElectra schemaDefinitionsElectra = + SchemaDefinitionsElectra.required(spec.getGenesisSchemaDefinitions()); + private final MiscHelpersElectra miscHelpersElectra = + new MiscHelpersElectra( + spec.getGenesisSpecConfig().toVersionElectra().orElseThrow(), + predicates, + schemaDefinitionsElectra); + private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); + + @Test + public void isFormerDepositMechanismDisabled_returnsTrueIfDisabled() { + final BeaconState preState = dataStructureUtil.randomBeaconState(); + + final BeaconState state = + BeaconStateElectra.required(preState) + .updated( + mutableState -> { + mutableState.setEth1DepositIndex(UInt64.valueOf(32)); + MutableBeaconStateElectra.required(mutableState) + .setDepositReceiptsStartIndex(UInt64.valueOf(33)); + }); + + assertThat(miscHelpersElectra.isFormerDepositMechanismDisabled(state)).isTrue(); + } + + @Test + public void isFormerDepositMechanismDisabled_returnsFalseIfNotDisabled() { + final BeaconState preState = dataStructureUtil.randomBeaconState(); + + final BeaconState state = + BeaconStateElectra.required(preState) + .updated( + mutableState -> { + mutableState.setEth1DepositIndex(UInt64.valueOf(32)); + MutableBeaconStateElectra.required(mutableState) + .setDepositReceiptsStartIndex( + SpecConfigElectra.UNSET_DEPOSIT_RECEIPTS_START_INDEX); + }); + + assertThat(miscHelpersElectra.isFormerDepositMechanismDisabled(state)).isFalse(); + } +} diff --git a/services/powchain/build.gradle b/services/powchain/build.gradle index c5ca21cc020..1862fda41a6 100644 --- a/services/powchain/build.gradle +++ b/services/powchain/build.gradle @@ -12,6 +12,7 @@ dependencies { implementation project(':infrastructure:logging') implementation project(':infrastructure:metrics') implementation project(':infrastructure:version') + implementation project(':storage') implementation project(':storage:api') implementation project(':infrastructure:http') implementation project(':infrastructure:io') diff --git a/services/powchain/src/main/java/tech/pegasys/teku/services/powchain/PowchainService.java b/services/powchain/src/main/java/tech/pegasys/teku/services/powchain/PowchainService.java index 3db8fdebc5e..0206b1bfc72 100644 --- a/services/powchain/src/main/java/tech/pegasys/teku/services/powchain/PowchainService.java +++ b/services/powchain/src/main/java/tech/pegasys/teku/services/powchain/PowchainService.java @@ -128,7 +128,7 @@ public PowchainService( final Eth1Provider eth1Provider = eth1Providers.getEth1Provider(); final String depositContract = powConfig.getDepositContract().toHexString(); - DepositEventsAccessor depositEventsAccessor = + final DepositEventsAccessor depositEventsAccessor = new DepositEventsAccessor(eth1Provider, depositContract); final ValidatingEth1EventsPublisher eth1EventsPublisher = diff --git a/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java b/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java index 7555452fa37..6065d1ba718 100644 --- a/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java +++ b/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java @@ -22,6 +22,8 @@ import tech.pegasys.teku.services.chainstorage.StorageService; import tech.pegasys.teku.services.executionlayer.ExecutionLayerService; import tech.pegasys.teku.services.powchain.PowchainService; +import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; +import tech.pegasys.teku.storage.client.RecentChainData; import tech.pegasys.teku.validator.client.ValidatorClientService; import tech.pegasys.teku.validator.client.slashingriskactions.DoppelgangerDetectionShutDown; import tech.pegasys.teku.validator.client.slashingriskactions.SlashedValidatorShutDown; @@ -30,7 +32,7 @@ public class BeaconNodeServiceController extends ServiceController { public BeaconNodeServiceController( - TekuConfiguration tekuConfig, final ServiceConfig serviceConfig) { + final TekuConfiguration tekuConfig, final ServiceConfig serviceConfig) { // Note services will be started in the order they are added here. services.add( new StorageService( @@ -49,13 +51,19 @@ public BeaconNodeServiceController( services.add(executionLayerService); maybeExecutionWeb3jClientProvider = executionLayerService.getEngineWeb3jClientProvider(); } - services.add(new BeaconChainService(serviceConfig, tekuConfig.beaconChain())); + final BeaconChainService beaconChainService = + new BeaconChainService(serviceConfig, tekuConfig.beaconChain()); + services.add(beaconChainService); services.add( new NatService( tekuConfig.natConfiguration(), tekuConfig.network().getListenPort(), tekuConfig.discovery().isDiscoveryEnabled())); - powchainService(tekuConfig, serviceConfig, maybeExecutionWeb3jClientProvider) + powchainService( + tekuConfig, + serviceConfig, + maybeExecutionWeb3jClientProvider, + beaconChainService.getBeaconChainController().getRecentChainData()) .ifPresent(services::add); final Optional maybeValidatorSlashedAction = @@ -74,12 +82,17 @@ public BeaconNodeServiceController( private Optional powchainService( final TekuConfiguration tekuConfig, final ServiceConfig serviceConfig, - final Optional maybeExecutionWeb3jClientProvider) { + final Optional maybeExecutionWeb3jClientProvider, + final RecentChainData recentChainData) { if (tekuConfig.beaconChain().interopConfig().isInteropEnabled() || (!tekuConfig.powchain().isEnabled() && maybeExecutionWeb3jClientProvider.isEmpty())) { return Optional.empty(); } - + final BeaconState finalizedState = recentChainData.getStore().getLatestFinalized().getState(); + // no need of initializing PowchainService if Eth1Data polling is not needed + if (tekuConfig.beaconChain().getSpec().isFormerDepositMechanismDisabled(finalizedState)) { + return Optional.empty(); + } return Optional.of( new PowchainService( serviceConfig, tekuConfig.powchain(), maybeExecutionWeb3jClientProvider));