diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/block/BlockManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/block/BlockManager.java index 0014e030763..f7c72cc171d 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/block/BlockManager.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/block/BlockManager.java @@ -132,6 +132,9 @@ public SafeFuture validateAndImportBlock( final Optional blockImportPerformance; + arrivalTimestamp.ifPresent( + arrivalTime -> recentChainData.setBlockTimelinessFromArrivalTime(block, arrivalTime)); + if (blockImportMetrics.isPresent()) { final BlockImportPerformance performance = new BlockImportPerformance(timeProvider, blockImportMetrics.get()); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifier.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifier.java index 4d5833010a1..6ffa9723d9f 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifier.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifier.java @@ -32,6 +32,8 @@ SafeFuture> getPayloadId( void onTerminalBlockReached(Bytes32 executionBlockHash); + boolean validatorIsConnected(UInt64 validatorIndex, UInt64 currentSlot); + long subscribeToForkChoiceUpdatedResult(ForkChoiceUpdatedResultSubscriber subscriber); boolean unsubscribeFromForkChoiceUpdatedResult(long subscriberId); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifierImpl.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifierImpl.java index 58549ce98e7..c2359e55397 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifierImpl.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceNotifierImpl.java @@ -108,6 +108,11 @@ public void onTerminalBlockReached(Bytes32 executionBlockHash) { eventThread.execute(() -> internalTerminalBlockReached(executionBlockHash)); } + @Override + public boolean validatorIsConnected(UInt64 validatorIndex, UInt64 currentSlot) { + return proposersDataManager.validatorIsConnected(validatorIndex, currentSlot); + } + @Override public void onPreparedProposersUpdated() { eventThread.execute(this::internalUpdatePreparableProposers); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManager.java index 828b39e6435..e2699db6b14 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManager.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManager.java @@ -139,6 +139,12 @@ public SafeFuture updateValidatorRegistrations( headState, signedValidatorRegistrations, currentSlot)); } + // used in ForkChoice validator_is_connected + public boolean validatorIsConnected(final UInt64 validatorIndex, final UInt64 currentSlot) { + final PreparedProposerInfo info = preparedProposerInfoByValidatorIndex.get(validatorIndex); + return info != null && !info.hasExpired(currentSlot); + } + private void updatePreparedProposerCache( final Collection preparedProposers, final UInt64 currentSlot) { final UInt64 expirySlot = diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManagerTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManagerTest.java new file mode 100644 index 00000000000..531a2a7cc42 --- /dev/null +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ProposersDataManagerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright Consensys Software Inc., 2023 + * + * 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.statetransition.forkchoice; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import java.util.List; +import java.util.Optional; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.junit.jupiter.api.Test; +import tech.pegasys.teku.ethereum.execution.types.Eth1Address; +import tech.pegasys.teku.infrastructure.async.eventthread.EventThread; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.TestSpecFactory; +import tech.pegasys.teku.spec.datastructures.operations.versions.bellatrix.BeaconPreparableProposer; +import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; +import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.storage.client.RecentChainData; + +class ProposersDataManagerTest { + + private final Spec spec = TestSpecFactory.createMinimalCapella(); + + private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); + + private final RecentChainData recentChainData = mock(RecentChainData.class); + + private final ExecutionLayerChannel channel = ExecutionLayerChannel.NOOP; + private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); + + private final Eth1Address defaultAddress = dataStructureUtil.randomEth1Address(); + private final ProposersDataManager manager = + new ProposersDataManager( + mock(EventThread.class), + spec, + metricsSystem, + channel, + recentChainData, + Optional.of(defaultAddress)); + + final List proposers = + List.of( + new BeaconPreparableProposer(UInt64.ONE, dataStructureUtil.randomEth1Address()), + new BeaconPreparableProposer(UInt64.ZERO, defaultAddress)); + + @Test + void validatorIsConnected_notFound_withEmptyPreparedList() { + assertThat(manager.validatorIsConnected(UInt64.ZERO, UInt64.ZERO)).isFalse(); + } + + @Test + void validatorIsConnected_found_withPreparedProposer() { + manager.updatePreparedProposers(proposers, UInt64.ONE); + assertThat(manager.validatorIsConnected(UInt64.ONE, UInt64.valueOf(1))).isTrue(); + } + + @Test + void validatorIsConnected_notFound_withDifferentPreparedProposer() { + manager.updatePreparedProposers(proposers, UInt64.ONE); + assertThat(manager.validatorIsConnected(UInt64.valueOf(2), UInt64.valueOf(2))).isFalse(); + } + + @Test + void validatorIsConnected_notFound_withExpiredPreparedProposer() { + manager.updatePreparedProposers(proposers, UInt64.ONE); + assertThat(manager.validatorIsConnected(UInt64.ONE, UInt64.valueOf(26))).isFalse(); + } +} diff --git a/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/forkchoice/StubForkChoiceNotifier.java b/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/forkchoice/StubForkChoiceNotifier.java index eb802ad7586..4dad1b6f17f 100644 --- a/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/forkchoice/StubForkChoiceNotifier.java +++ b/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/forkchoice/StubForkChoiceNotifier.java @@ -69,4 +69,9 @@ public SafeFuture> getPayloadId( @Override public void onTerminalBlockReached(final Bytes32 executionBlockHash) {} + + @Override + public boolean validatorIsConnected(UInt64 validatorIndex, UInt64 currentSlot) { + return true; + } } diff --git a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java index e80f0764336..e51bd1cb7ae 100644 --- a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java +++ b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java @@ -401,6 +401,7 @@ protected SafeFuture initialize() { metricsSystem, storeConfig, beaconAsyncRunner, + timeProvider, storageQueryChannel, storageUpdateChannel, voteUpdateChannel, diff --git a/storage/src/main/java/tech/pegasys/teku/storage/client/BlockTimelinessTracker.java b/storage/src/main/java/tech/pegasys/teku/storage/client/BlockTimelinessTracker.java new file mode 100644 index 00000000000..e4a3a754797 --- /dev/null +++ b/storage/src/main/java/tech/pegasys/teku/storage/client/BlockTimelinessTracker.java @@ -0,0 +1,93 @@ +/* + * Copyright Consensys Software Inc., 2023 + * + * 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.storage.client; + +import static tech.pegasys.teku.spec.constants.NetworkConstants.INTERVALS_PER_SLOT; + +import java.util.Map; +import java.util.Optional; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.infrastructure.collections.LimitedMap; +import tech.pegasys.teku.infrastructure.time.TimeProvider; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; + +public class BlockTimelinessTracker { + private static final Logger LOG = LogManager.getLogger(); + private final Map blockTimeliness; + private final TimeProvider timeProvider; + private final Spec spec; + private final RecentChainData recentChainData; + + // implements is_timely from Consensus Spec + public BlockTimelinessTracker( + final Spec spec, final RecentChainData recentChainData, final TimeProvider timeProvider) { + this.spec = spec; + final int epochsForTimeliness = + Math.max(spec.getGenesisSpecConfig().getReorgMaxEpochsSinceFinalization(), 3); + this.blockTimeliness = + LimitedMap.createSynchronizedNatural( + spec.getGenesisSpec().getSlotsPerEpoch() * epochsForTimeliness); + this.timeProvider = timeProvider; + this.recentChainData = recentChainData; + } + + public void setBlockTimelinessFromArrivalTime( + final SignedBeaconBlock block, final UInt64 arrivalTimeMillis) { + final UInt64 genesisTime = recentChainData.getGenesisTime(); + final UInt64 computedSlot = spec.getCurrentSlot(timeProvider.getTimeInSeconds(), genesisTime); + final Bytes32 root = block.getRoot(); + if (computedSlot.isGreaterThan(block.getMessage().getSlot())) { + LOG.debug( + "Block {}:{} is before computed slot {}, timeliness set to false.", + root, + block.getSlot(), + computedSlot); + blockTimeliness.put(root, false); + return; + } + recentChainData + .getCurrentSlot() + .ifPresent( + slot -> { + final UInt64 slotStartTimeMillis = + spec.getSlotStartTimeMillis(slot, genesisTime.times(1000)); + final int millisIntoSlot = + arrivalTimeMillis.minusMinZero(slotStartTimeMillis).intValue(); + + final UInt64 timelinessLimit = + spec.getMillisPerSlot(slot).dividedBy(INTERVALS_PER_SLOT); + + final boolean isTimely = + block.getMessage().getSlot().equals(slot) + && timelinessLimit.isGreaterThan(millisIntoSlot); + LOG.debug( + "Block {}:{} arrived at {} ms into slot {}, timeliness limit is {} ms. result: {}", + root, + block.getSlot(), + millisIntoSlot, + computedSlot, + timelinessLimit, + isTimely); + blockTimeliness.put(root, isTimely); + }); + } + + public Optional isBlockTimely(final Bytes32 root) { + return Optional.ofNullable(blockTimeliness.get(root)); + } +} diff --git a/storage/src/main/java/tech/pegasys/teku/storage/client/RecentChainData.java b/storage/src/main/java/tech/pegasys/teku/storage/client/RecentChainData.java index e855aa8582a..d3f66a473e8 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/client/RecentChainData.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/client/RecentChainData.java @@ -35,6 +35,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.metrics.TekuMetricCategory; +import tech.pegasys.teku.infrastructure.time.TimeProvider; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; @@ -98,10 +99,13 @@ public abstract class RecentChainData implements StoreUpdateHandler { private volatile Optional chainHead = Optional.empty(); private volatile UInt64 genesisTime; + private final BlockTimelinessTracker blockTimelinessTracker; + RecentChainData( final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final StoreConfig storeConfig, + final TimeProvider timeProvider, final BlockProvider blockProvider, final StateAndBlockSummaryProvider stateProvider, final EarliestBlobSidecarSlotProvider earliestBlobSidecarSlotProvider, @@ -120,6 +124,7 @@ public abstract class RecentChainData implements StoreUpdateHandler { this.chainHeadChannel = chainHeadChannel; this.storageUpdateChannel = storageUpdateChannel; this.finalizedCheckpointChannel = finalizedCheckpointChannel; + this.blockTimelinessTracker = new BlockTimelinessTracker(spec, this, timeProvider); reorgCounter = metricsSystem.createCounter( TekuMetricCategory.BEACON, @@ -613,4 +618,13 @@ public List getAllBlockRootsAtSlot(final UInt64 slot) { .map(forkChoiceStrategy -> forkChoiceStrategy.getBlockRootsAtSlot(slot)) .orElse(Collections.emptyList()); } + + public void setBlockTimelinessFromArrivalTime( + final SignedBeaconBlock block, final UInt64 arrivalTime) { + blockTimelinessTracker.setBlockTimelinessFromArrivalTime(block, arrivalTime); + } + + public Optional getBlockTimeliness(final Bytes32 blockRoot) { + return blockTimelinessTracker.isBlockTimely(blockRoot); + } } diff --git a/storage/src/main/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainData.java b/storage/src/main/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainData.java index 57aa724aa26..56d44024cc2 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainData.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainData.java @@ -26,6 +26,7 @@ import tech.pegasys.teku.dataproviders.lookup.StateAndBlockSummaryProvider; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.time.TimeProvider; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.storage.api.ChainHeadChannel; @@ -49,6 +50,7 @@ public StorageBackedRecentChainData( final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final StoreConfig storeConfig, + final TimeProvider timeProvider, final StorageQueryChannel storageQueryChannel, final StorageUpdateChannel storageUpdateChannel, final VoteUpdateChannel voteUpdateChannel, @@ -59,6 +61,7 @@ public StorageBackedRecentChainData( asyncRunner, metricsSystem, storeConfig, + timeProvider, storageQueryChannel::getHotBlocksByRoot, storageQueryChannel::getHotStateAndBlockSummaryByBlockRoot, storageQueryChannel::getEarliestAvailableBlobSidecarSlot, @@ -77,6 +80,7 @@ public static SafeFuture create( final MetricsSystem metricsSystem, final StoreConfig storeConfig, final AsyncRunner asyncRunner, + final TimeProvider timeProvider, final StorageQueryChannel storageQueryChannel, final StorageUpdateChannel storageUpdateChannel, final VoteUpdateChannel voteUpdateChannel, @@ -88,6 +92,7 @@ public static SafeFuture create( asyncRunner, metricsSystem, storeConfig, + timeProvider, storageQueryChannel, storageUpdateChannel, voteUpdateChannel, @@ -103,6 +108,7 @@ public static RecentChainData createImmediately( final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final StoreConfig storeConfig, + final TimeProvider timeProvider, final StorageQueryChannel storageQueryChannel, final StorageUpdateChannel storageUpdateChannel, final VoteUpdateChannel voteUpdateChannel, @@ -114,6 +120,7 @@ public static RecentChainData createImmediately( asyncRunner, metricsSystem, storeConfig, + timeProvider, storageQueryChannel, storageUpdateChannel, voteUpdateChannel, diff --git a/storage/src/test/java/tech/pegasys/teku/storage/client/BlockTimelinessTrackerTest.java b/storage/src/test/java/tech/pegasys/teku/storage/client/BlockTimelinessTrackerTest.java new file mode 100644 index 00000000000..e32045276b8 --- /dev/null +++ b/storage/src/test/java/tech/pegasys/teku/storage/client/BlockTimelinessTrackerTest.java @@ -0,0 +1,98 @@ +/* + * Copyright Consensys Software Inc., 2023 + * + * 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.storage.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import org.apache.tuweni.bytes.Bytes32; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import tech.pegasys.teku.infrastructure.time.StubTimeProvider; +import tech.pegasys.teku.infrastructure.time.TimeProvider; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.TestSpecFactory; +import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; +import tech.pegasys.teku.spec.util.DataStructureUtil; + +class BlockTimelinessTrackerTest { + private final Spec spec = TestSpecFactory.createDefault(); + private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); + private final int millisPerSlot = spec.getGenesisSpecConfig().getSecondsPerSlot() * 1000; + private final RecentChainData recentChainData = mock(RecentChainData.class); + private final UInt64 slot = UInt64.ONE; + + private TimeProvider timeProvider; + private Bytes32 blockRoot; + private SignedBlockAndState signedBlockAndState; + private BlockTimelinessTracker tracker; + + @BeforeEach + void setup() { + signedBlockAndState = dataStructureUtil.randomSignedBlockAndState(slot); + blockRoot = signedBlockAndState.getBlock().getMessage().getRoot(); + timeProvider = + StubTimeProvider.withTimeInSeconds(signedBlockAndState.getState().getGenesisTime()); + tracker = new BlockTimelinessTracker(spec, recentChainData, timeProvider); + + when(recentChainData.getGenesisTime()) + .thenReturn(signedBlockAndState.getState().getGenesisTime()); + when(recentChainData.getCurrentSlot()).thenReturn(Optional.of(UInt64.ONE)); + } + + @Test + void blockTimeliness_shouldReportTimelinessIfSet() { + final UInt64 computedTime = computeTime(slot, 500); + + tracker.setBlockTimelinessFromArrivalTime(signedBlockAndState.getBlock(), computedTime); + assertThat(tracker.isBlockTimely(blockRoot)).contains(true); + } + + @Test + void blockTimeliness_shouldReportFalseIfLate() { + final UInt64 computedTime = computeTime(slot, 2100); + + tracker.setBlockTimelinessFromArrivalTime(signedBlockAndState.getBlock(), computedTime); + assertThat(tracker.isBlockTimely(blockRoot)).contains(false); + } + + @Test + void blockTimeliness_shouldReportFalseIfAtLimit() { + final UInt64 computedTime = computeTime(slot, 2000); + + tracker.setBlockTimelinessFromArrivalTime(signedBlockAndState.getBlock(), computedTime); + assertThat(tracker.isBlockTimely(blockRoot)).contains(false); + } + + @Test + void blockTimeliness_ifBlockFromFuture() { + final UInt64 computedTime = computeTime(slot, 2100); + + tracker.setBlockTimelinessFromArrivalTime( + dataStructureUtil.randomSignedBeaconBlock(0), computedTime); + assertThat(tracker.isBlockTimely(blockRoot)).isEmpty(); + } + + @Test + void blockTimeliness_shouldReportEmptyIfNotSet() { + assertThat(tracker.isBlockTimely(blockRoot)).isEmpty(); + } + + private UInt64 computeTime(final UInt64 slot, final long timeIntoSlot) { + return timeProvider.getTimeInMillis().plus(slot.times(millisPerSlot)).plus(timeIntoSlot); + } +} diff --git a/storage/src/test/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainDataTest.java b/storage/src/test/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainDataTest.java index 8b602676966..1b07843dc54 100644 --- a/storage/src/test/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainDataTest.java +++ b/storage/src/test/java/tech/pegasys/teku/storage/client/StorageBackedRecentChainDataTest.java @@ -31,6 +31,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.async.StubAsyncRunner; import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem; +import tech.pegasys.teku.infrastructure.time.SystemTimeProvider; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.TestSpecFactory; @@ -76,6 +77,7 @@ public void storageBackedClient_storeInitializeViaGetStoreRequest() new StubMetricsSystem(), storeConfig, asyncRunner, + new SystemTimeProvider(), storageQueryChannel, storageUpdateChannel, voteUpdateChannel, @@ -123,6 +125,7 @@ public void storageBackedClient_storeInitializeViaNewGenesisState() new StubMetricsSystem(), storeConfig, asyncRunner, + new SystemTimeProvider(), storageQueryChannel, storageUpdateChannel, voteUpdateChannel, @@ -173,6 +176,7 @@ public void storageBackedClient_storeInitializeViaGetStoreRequestAfterTimeout() new StubMetricsSystem(), StoreConfig.createDefault(), asyncRunner, + new SystemTimeProvider(), storageQueryChannel, storageUpdateChannel, voteUpdateChannel, @@ -219,6 +223,7 @@ public void storageBackedClient_storeInitializeViaGetStoreRequestAfterIOExceptio new StubMetricsSystem(), StoreConfig.createDefault(), asyncRunner, + new SystemTimeProvider(), storageQueryChannel, storageUpdateChannel, voteUpdateChannel, diff --git a/storage/src/testFixtures/java/tech/pegasys/teku/storage/client/MemoryOnlyRecentChainData.java b/storage/src/testFixtures/java/tech/pegasys/teku/storage/client/MemoryOnlyRecentChainData.java index cfd32ec42a8..03513fae264 100644 --- a/storage/src/testFixtures/java/tech/pegasys/teku/storage/client/MemoryOnlyRecentChainData.java +++ b/storage/src/testFixtures/java/tech/pegasys/teku/storage/client/MemoryOnlyRecentChainData.java @@ -22,6 +22,8 @@ import tech.pegasys.teku.dataproviders.lookup.EarliestBlobSidecarSlotProvider; import tech.pegasys.teku.dataproviders.lookup.StateAndBlockSummaryProvider; import tech.pegasys.teku.infrastructure.async.AsyncRunner; +import tech.pegasys.teku.infrastructure.time.SystemTimeProvider; +import tech.pegasys.teku.infrastructure.time.TimeProvider; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.storage.api.ChainHeadChannel; @@ -39,6 +41,7 @@ private MemoryOnlyRecentChainData( final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final StoreConfig storeConfig, + final TimeProvider timeProvider, final StorageUpdateChannel storageUpdateChannel, final VoteUpdateChannel voteUpdateChannel, final FinalizedCheckpointChannel finalizedCheckpointChannel, @@ -48,6 +51,7 @@ private MemoryOnlyRecentChainData( asyncRunner, metricsSystem, storeConfig, + timeProvider, BlockProvider.NOOP, StateAndBlockSummaryProvider.NOOP, EarliestBlobSidecarSlotProvider.NOOP, @@ -87,6 +91,7 @@ public RecentChainData build() { SYNC_RUNNER, new NoOpMetricsSystem(), storeConfig, + new SystemTimeProvider(), storageUpdateChannel, votes -> {}, finalizedCheckpointChannel, diff --git a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/FileBackedStorageSystemBuilder.java b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/FileBackedStorageSystemBuilder.java index 3d4ae3df271..0b2a34db26a 100644 --- a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/FileBackedStorageSystemBuilder.java +++ b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/FileBackedStorageSystemBuilder.java @@ -18,6 +18,7 @@ import java.nio.file.Path; import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem; +import tech.pegasys.teku.infrastructure.time.SystemTimeProvider; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.generator.ChainBuilder; import tech.pegasys.teku.storage.server.Database; @@ -59,6 +60,7 @@ public StorageSystem build() { createRestartSupplier(), storageMode, storeConfig, + new SystemTimeProvider(), spec, ChainBuilder.create(spec)); } diff --git a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/InMemoryStorageSystemBuilder.java b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/InMemoryStorageSystemBuilder.java index 86d3491bdc2..6df97379790 100644 --- a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/InMemoryStorageSystemBuilder.java +++ b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/InMemoryStorageSystemBuilder.java @@ -17,6 +17,7 @@ import java.util.List; import tech.pegasys.teku.bls.BLSKeyPair; +import tech.pegasys.teku.infrastructure.time.SystemTimeProvider; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.datastructures.interop.MockStartValidatorKeyPairFactory; @@ -98,6 +99,7 @@ public StorageSystem build() { createRestartSupplier(), storageMode, storeConfig, + new SystemTimeProvider(), spec, ChainBuilder.create(spec, validatorKeys)); } diff --git a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/StorageSystem.java b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/StorageSystem.java index 9378bd7abd3..b447c4a7225 100644 --- a/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/StorageSystem.java +++ b/storage/src/testFixtures/java/tech/pegasys/teku/storage/storageSystem/StorageSystem.java @@ -19,6 +19,7 @@ import tech.pegasys.teku.beacon.pow.api.TrackingEth1EventsChannel; import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem; import tech.pegasys.teku.infrastructure.time.SystemTimeProvider; +import tech.pegasys.teku.infrastructure.time.TimeProvider; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.datastructures.blocks.StateAndBlockSummary; import tech.pegasys.teku.spec.generator.ChainBuilder; @@ -85,6 +86,7 @@ static StorageSystem create( final RestartedStorageSupplier restartedSupplier, final StateStorageMode storageMode, final StoreConfig storeConfig, + final TimeProvider timeProvider, final Spec spec, final ChainBuilder chainBuilder) { final StubMetricsSystem metricsSystem = new StubMetricsSystem(); @@ -101,6 +103,7 @@ static StorageSystem create( SYNC_RUNNER, metricsSystem, storeConfig, + timeProvider, chainStorageServer, chainStorageServer, chainStorageServer,