From baf23a58b8654bfabf7e63cd1c89fb3f26a5588e Mon Sep 17 00:00:00 2001 From: Dmitrii Shmatko Date: Fri, 20 Dec 2024 23:57:33 +0100 Subject: [PATCH] Remove TTD Bellatrix merge configuration option --- .../teku/beacon/sync/SyncingNodeManager.java | 3 +- ...tractDataBackedRestAPIIntegrationTest.java | 4 +- .../benchmarks/EpochTransitionBenchmark.java | 2 +- .../pegasys/teku/benchmarks/ProfilingRun.java | 4 +- .../teku/benchmarks/TransitionBenchmark.java | 2 +- .../forkchoice/ForkChoiceTestExecutor.java | 5 +- .../web3j/Web3JExecutionEngineClient.java | 2 - .../ExecutionHandlerClientTest.java | 5 +- .../datastructures/execution/PowBlock.java | 14 +- .../ExecutionLayerChannelStub.java | 8 +- .../helpers/BellatrixTransitionHelpers.java | 52 +----- .../BellatrixTransitionHelpersTest.java | 77 ++------ .../AttestationManagerIntegrationTest.java | 3 +- .../forkchoice/ForkChoicePayloadExecutor.java | 4 +- .../MergeTransitionBlockValidator.java | 10 +- .../forkchoice/TerminalPowBlockMonitor.java | 169 ++---------------- .../block/BlockImporterTest.java | 2 +- .../block/BlockManagerTest.java | 4 +- .../forkchoice/ForkChoiceTest.java | 13 +- .../MergeTransitionBlockValidatorTest.java | 93 +++------- .../TerminalPowBlockMonitorTest.java | 116 ++---------- .../teku/statetransition/BeaconChainUtil.java | 8 +- .../ForkChoiceIntegrationTest.java | 3 +- .../beaconchain/BeaconChainController.java | 5 +- 24 files changed, 89 insertions(+), 519 deletions(-) diff --git a/beacon/sync/src/testFixtures/java/tech/pegasys/teku/beacon/sync/SyncingNodeManager.java b/beacon/sync/src/testFixtures/java/tech/pegasys/teku/beacon/sync/SyncingNodeManager.java index 5256e4a6e7a..0c9e13a92f2 100644 --- a/beacon/sync/src/testFixtures/java/tech/pegasys/teku/beacon/sync/SyncingNodeManager.java +++ b/beacon/sync/src/testFixtures/java/tech/pegasys/teku/beacon/sync/SyncingNodeManager.java @@ -52,7 +52,6 @@ import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; import tech.pegasys.teku.statetransition.BeaconChainUtil; @@ -115,7 +114,7 @@ public static SyncingNodeManager create( chainUtil.initializeStorage(); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); final ForkChoice forkChoice = new ForkChoice( diff --git a/data/beaconrestapi/src/integration-test/java/tech/pegasys/teku/beaconrestapi/AbstractDataBackedRestAPIIntegrationTest.java b/data/beaconrestapi/src/integration-test/java/tech/pegasys/teku/beaconrestapi/AbstractDataBackedRestAPIIntegrationTest.java index ed9f5d3a216..84d7396268f 100644 --- a/data/beaconrestapi/src/integration-test/java/tech/pegasys/teku/beaconrestapi/AbstractDataBackedRestAPIIntegrationTest.java +++ b/data/beaconrestapi/src/integration-test/java/tech/pegasys/teku/beaconrestapi/AbstractDataBackedRestAPIIntegrationTest.java @@ -67,7 +67,6 @@ import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerBlockProductionManager; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.generator.ChainBuilder; import tech.pegasys.teku.statetransition.MappedOperationPool; import tech.pegasys.teku.statetransition.OperationPool; @@ -200,8 +199,7 @@ private void setupStorage( recentChainData, BlobSidecarManager.NOOP, new NoopForkChoiceNotifier(), - new MergeTransitionBlockValidator( - spec, recentChainData, ExecutionLayerChannel.NOOP), + new MergeTransitionBlockValidator(spec, recentChainData), storageSystem.getMetricsSystem()); final Function> beaconBlockSchemaSupplier = slot -> spec.atSlot(slot).getSchemaDefinitions().getBeaconBlockBodySchema(); diff --git a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/EpochTransitionBenchmark.java b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/EpochTransitionBenchmark.java index 6caeac08de4..364455e8132 100644 --- a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/EpochTransitionBenchmark.java +++ b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/EpochTransitionBenchmark.java @@ -120,7 +120,7 @@ public void init() throws Exception { recentChainData = MemoryOnlyRecentChainData.create(spec); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); ForkChoice forkChoice = new ForkChoice( spec, diff --git a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/ProfilingRun.java b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/ProfilingRun.java index 4e2d92dde26..86fe524abce 100644 --- a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/ProfilingRun.java +++ b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/ProfilingRun.java @@ -100,7 +100,7 @@ public void importBlocks() throws Exception { RecentChainData recentChainData = MemoryOnlyRecentChainData.create(spec); recentChainData.initializeFromGenesis(initialState, UInt64.ZERO); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); ForkChoice forkChoice = new ForkChoice( spec, @@ -195,7 +195,7 @@ public void importBlocksMemProfiling() throws Exception { recentChainData.initializeFromGenesis(initialState, UInt64.ZERO); initialState = null; final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); ForkChoice forkChoice = new ForkChoice( spec, diff --git a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/TransitionBenchmark.java b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/TransitionBenchmark.java index 295b2062c8b..637831235e8 100644 --- a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/TransitionBenchmark.java +++ b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/TransitionBenchmark.java @@ -97,7 +97,7 @@ public void init() throws Exception { wsValidator = WeakSubjectivityFactory.lenientValidator(); recentChainData = MemoryOnlyRecentChainData.create(spec); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); ForkChoice forkChoice = new ForkChoice( spec, diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java index 0b0f9570da4..e90dc9f0f81 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java @@ -59,7 +59,6 @@ import tech.pegasys.teku.spec.datastructures.state.AnchorPoint; import tech.pegasys.teku.spec.datastructures.state.Checkpoint; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; import tech.pegasys.teku.spec.executionlayer.ExecutionPayloadStatus; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; @@ -123,7 +122,7 @@ spec, new SignedBlockAndState(anchorBlock, anchorState)), spec.getSlotStartTime(anchorBlock.getSlot(), anchorState.getGenesisTime())); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); final InlineEventThread eventThread = new InlineEventThread(); final KZG kzg = KzgRetriever.getKzgWithLoadedTrustedSetup(spec, testDefinition.getConfigName()); final StubBlobSidecarManager blobSidecarManager = new StubBlobSidecarManager(kzg); @@ -251,7 +250,7 @@ private PowBlock parsePowBlock(final Bytes data) { .toUnsignedBigInteger(ByteOrder.LITTLE_ENDIAN)); // We don't get a timestamp but as long as it's in the past that's fine final UInt64 timestamp = UInt64.ZERO; - return new PowBlock(blockHash, parentHash, totalDifficulty, timestamp); + return new PowBlock(blockHash, parentHash, timestamp); }); } diff --git a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/web3j/Web3JExecutionEngineClient.java b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/web3j/Web3JExecutionEngineClient.java index 6eed83dd565..0f8f693c58c 100644 --- a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/web3j/Web3JExecutionEngineClient.java +++ b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/web3j/Web3JExecutionEngineClient.java @@ -23,7 +23,6 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.Request; import org.web3j.protocol.core.methods.response.EthBlock; @@ -87,7 +86,6 @@ private static PowBlock eth1BlockToPowBlock(final EthBlock.Block eth1Block) { : new PowBlock( Bytes32.fromHexStringStrict(eth1Block.getHash()), Bytes32.fromHexStringStrict(eth1Block.getParentHash()), - UInt256.valueOf(eth1Block.getTotalDifficulty()), UInt64.valueOf(eth1Block.getTimestamp())); } diff --git a/ethereum/executionlayer/src/test/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionHandlerClientTest.java b/ethereum/executionlayer/src/test/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionHandlerClientTest.java index efa5cd76940..e92a3123c49 100644 --- a/ethereum/executionlayer/src/test/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionHandlerClientTest.java +++ b/ethereum/executionlayer/src/test/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionHandlerClientTest.java @@ -52,10 +52,7 @@ void eth1GetPowBlock_shouldCallExecutionClient() { private PowBlock createPowBlock(final Bytes32 blockHash) { return new PowBlock( - blockHash, - dataStructureUtil.randomBytes32(), - dataStructureUtil.randomUInt256(), - dataStructureUtil.randomUInt64()); + blockHash, dataStructureUtil.randomBytes32(), dataStructureUtil.randomUInt64()); } @SuppressWarnings("FutureReturnValueIgnored") diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/PowBlock.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/PowBlock.java index cdeebd85868..d5ab6624d55 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/PowBlock.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/PowBlock.java @@ -15,24 +15,17 @@ import com.google.common.base.MoreObjects; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.infrastructure.unsigned.UInt64; public class PowBlock { private final Bytes32 blockHash; private final Bytes32 parentHash; - private final UInt256 totalDifficulty; private final UInt64 blockTimestamp; - public PowBlock( - final Bytes32 blockHash, - final Bytes32 parentHash, - final UInt256 totalDifficulty, - final UInt64 blockTimestamp) { + public PowBlock(final Bytes32 blockHash, final Bytes32 parentHash, final UInt64 blockTimestamp) { this.blockHash = blockHash; this.parentHash = parentHash; - this.totalDifficulty = totalDifficulty; this.blockTimestamp = blockTimestamp; } @@ -44,10 +37,6 @@ public Bytes32 getParentHash() { return parentHash; } - public UInt256 getTotalDifficulty() { - return totalDifficulty; - } - public UInt64 getBlockTimestamp() { return blockTimestamp; } @@ -57,7 +46,6 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("blockHash", blockHash) .add("parentHash", parentHash) - .add("totalDifficulty", totalDifficulty) .add("blockTimestamp", blockTimestamp) .toString(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/executionlayer/ExecutionLayerChannelStub.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/executionlayer/ExecutionLayerChannelStub.java index 62932ca4235..5ff539161d7 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/executionlayer/ExecutionLayerChannelStub.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/executionlayer/ExecutionLayerChannelStub.java @@ -298,7 +298,6 @@ public SafeFuture engineGetPayload( new PowBlock( executionPayload.getBlockHash(), executionPayload.getParentHash(), - UInt256.ZERO, payloadAttributes.getTimestamp())); headAndAttrs.currentExecutionPayload = Optional.of(executionPayload); @@ -586,11 +585,8 @@ private void prepareTransitionBlocks(final UInt64 bellatrixActivationTime) { terminalBlockHash = configTerminalBlockHash; } - terminalBlockParent = - new PowBlock(TERMINAL_BLOCK_PARENT_HASH, Bytes32.ZERO, UInt256.ZERO, UInt64.ZERO); - terminalBlock = - new PowBlock( - terminalBlockHash, TERMINAL_BLOCK_PARENT_HASH, terminalTotalDifficulty, transitionTime); + terminalBlockParent = new PowBlock(TERMINAL_BLOCK_PARENT_HASH, Bytes32.ZERO, UInt64.ZERO); + terminalBlock = new PowBlock(terminalBlockHash, TERMINAL_BLOCK_PARENT_HASH, transitionTime); } private HeadAndAttributes getCachedHeadAndAttributes( diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpers.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpers.java index 81ab65b1d84..21c545494e6 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpers.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpers.java @@ -16,13 +16,10 @@ import static tech.pegasys.teku.infrastructure.async.SafeFuture.completedFuture; import java.util.Optional; -import org.apache.tuweni.bytes.Bytes32; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.config.SpecConfigBellatrix; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; -import tech.pegasys.teku.spec.datastructures.execution.PowBlock; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; public class BellatrixTransitionHelpers { @@ -46,21 +43,19 @@ public BellatrixTransitionHelpers( *

That is, the PoW chain stops as soon as one block has exceeded TTD and from that point on * merges into the beacon chain. * - * @param executionLayer the execution layer to use for verification * @param executionPayloadSummary the first non-empty payload on the beacon chain * @param blockSlot the slot of the block the executionPayload is from * @return a future containing the validation result for the execution payload */ public SafeFuture validateMergeBlock( - final ExecutionLayerChannel executionLayer, - final ExecutionPayloadSummary executionPayloadSummary, - final UInt64 blockSlot) { + final ExecutionPayloadSummary executionPayloadSummary, final UInt64 blockSlot) { if (!specConfig.getTerminalBlockHash().isZero()) { return validateWithTerminalBlockHash(executionPayloadSummary, blockSlot); } - return executionLayer - .eth1GetPowBlock(executionPayloadSummary.getParentHash()) - .thenCompose(maybePowBlock -> validatePowBlock(executionLayer, maybePowBlock)); + + return SafeFuture.completedFuture( + PayloadStatus.invalid( + Optional.empty(), Optional.of("Total difficulty check is no more supported"))); } private SafeFuture validateWithTerminalBlockHash( @@ -76,44 +71,7 @@ private SafeFuture validateWithTerminalBlockHash( return SafeFuture.completedFuture(PayloadStatus.VALID); } - private SafeFuture validatePowBlock( - final ExecutionLayerChannel executionLayer, final Optional maybePowBlock) { - if (maybePowBlock.isEmpty()) { - return completedFuture(PayloadStatus.SYNCING); - } - final PowBlock powBlock = maybePowBlock.get(); - if (isBelowTotalDifficulty(powBlock)) { - return invalid("PowBlock has not reached terminal total difficulty"); - } - return validateParentPowBlock(executionLayer, powBlock.getParentHash()); - } - private static SafeFuture invalid(final String message) { return completedFuture(PayloadStatus.invalid(Optional.empty(), Optional.of(message))); } - - private SafeFuture validateParentPowBlock( - final ExecutionLayerChannel executionLayer, final Bytes32 parentBlockHash) { - // fast check for genesis - if (parentBlockHash.isZero()) { - return completedFuture(PayloadStatus.VALID); - } - return executionLayer - .eth1GetPowBlock(parentBlockHash) - .thenCompose( - maybeParentPowBlock -> { - if (maybeParentPowBlock.isEmpty()) { - return completedFuture(PayloadStatus.SYNCING); - } - final PowBlock parentPowBlock = maybeParentPowBlock.get(); - if (!isBelowTotalDifficulty(parentPowBlock)) { - return invalid("Parent PowBlock exceeds terminal total difficulty"); - } - return completedFuture(PayloadStatus.VALID); - }); - } - - private boolean isBelowTotalDifficulty(final PowBlock powBlock) { - return powBlock.getTotalDifficulty().lessThan(specConfig.getTerminalTotalDifficulty()); - } } diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpersTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpersTest.java index a95bc2e08ae..ddbaaa42537 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpersTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/bellatrix/helpers/BellatrixTransitionHelpersTest.java @@ -14,23 +14,15 @@ package tech.pegasys.teku.spec.logic.versions.bellatrix.helpers; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static tech.pegasys.teku.infrastructure.async.SafeFuture.completedFuture; import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; -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.Spec; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; -import tech.pegasys.teku.spec.datastructures.execution.PowBlock; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionPayloadStatus; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; import tech.pegasys.teku.spec.util.DataStructureUtil; @@ -39,52 +31,15 @@ class BellatrixTransitionHelpersTest { private final Spec spec = TestSpecFactory.createMinimalBellatrix(); private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); - private final ExecutionLayerChannel executionLayer = mock(ExecutionLayerChannel.class); - private final UInt256 terminalDifficulty = - spec.getGenesisSpecConfig().toVersionBellatrix().orElseThrow().getTerminalTotalDifficulty(); - private final UInt64 slot = dataStructureUtil.randomUInt64(); - private final ExecutionPayload payload = dataStructureUtil.randomExecutionPayload(); - @BeforeEach - void setUp() { - when(executionLayer.eth1GetPowBlock(any())).thenReturn(completedFuture(Optional.empty())); - } - - @Test - void shouldBeSyncingIfPowBlockIsNotAvailable() { - assertPayloadResultStatus(ExecutionPayloadStatus.SYNCING); - } - - @Test - void shouldBeSyncingIfPowParentIsNotAvailable() { - withPowBlock(payload.getParentHash(), terminalDifficulty); - - assertPayloadResultStatus(ExecutionPayloadStatus.SYNCING); - } - - @Test - void shouldBeInvalidIfTotalDifficultyNotReached() { - withPowBlock(payload.getParentHash(), terminalDifficulty.subtract(1)); - - assertPayloadResultStatus(ExecutionPayloadStatus.INVALID); - } - - @Test - void shouldBeInvalidIfParentTotalDifficultyIsReached() { - final PowBlock powBlock = withPowBlock(payload.getParentHash(), terminalDifficulty.plus(1)); - withPowBlock(powBlock.getParentHash(), terminalDifficulty); - - assertPayloadResultStatus(ExecutionPayloadStatus.INVALID); - } - @Test - void shouldBeValidIfTerminalDifficultyConditionsMet() { - final PowBlock powBlock = withPowBlock(payload.getParentHash(), terminalDifficulty.plus(1)); - withPowBlock(powBlock.getParentHash(), terminalDifficulty.subtract(1)); - - assertThat(validateMergeBlock()).isCompletedWithValue(PayloadStatus.VALID); + void shouldBeInvalidForTTDNotSupported() { + assertThat(validateMergeBlock()) + .isCompletedWithValue( + PayloadStatus.invalid( + Optional.empty(), Optional.of("Total difficulty check is no more supported"))); } @Test @@ -96,7 +51,7 @@ void shouldBeValidWhenTerminalBlockHashMatchesInActivationEpoch() { spec.getGenesisSpec() .getBellatrixTransitionHelpers() .orElseThrow() - .validateMergeBlock(executionLayer, payload, blockSlot); + .validateMergeBlock(payload, blockSlot); assertPayloadResultStatus(result, ExecutionPayloadStatus.VALID); } @@ -109,7 +64,7 @@ void shouldBeValidWhenTerminalBlockHashMatchesAfterActivationEpoch() { spec.getGenesisSpec() .getBellatrixTransitionHelpers() .orElseThrow() - .validateMergeBlock(executionLayer, payload, blockSlot); + .validateMergeBlock(payload, blockSlot); assertPayloadResultStatus(result, ExecutionPayloadStatus.VALID); } @@ -122,7 +77,7 @@ void shouldBeInvalidWhenTerminalBlockHashDoesNotMatch() { spec.getGenesisSpec() .getBellatrixTransitionHelpers() .orElseThrow() - .validateMergeBlock(executionLayer, payload, blockSlot); + .validateMergeBlock(payload, blockSlot); assertPayloadResultStatus(result, ExecutionPayloadStatus.INVALID); } @@ -135,7 +90,7 @@ void shouldBeInvalidWhenBeforeActivationEpoch() { spec.getGenesisSpec() .getBellatrixTransitionHelpers() .orElseThrow() - .validateMergeBlock(executionLayer, payload, blockSlot); + .validateMergeBlock(payload, blockSlot); assertPayloadResultStatus(result, ExecutionPayloadStatus.INVALID); } @@ -149,23 +104,11 @@ private Spec createSpec( .terminalBlockHashActivationEpoch(terminalBlockHashActivationEpoch))); } - private PowBlock withPowBlock(final Bytes32 hash, final UInt256 totalDifficulty) { - final PowBlock powBlock = - new PowBlock(hash, dataStructureUtil.randomBytes32(), totalDifficulty, UInt64.ZERO); - when(executionLayer.eth1GetPowBlock(powBlock.getBlockHash())) - .thenReturn(completedFuture(Optional.of(powBlock))); - return powBlock; - } - - private void assertPayloadResultStatus(final ExecutionPayloadStatus expectedStatus) { - assertPayloadResultStatus(validateMergeBlock(), expectedStatus); - } - private SafeFuture validateMergeBlock() { return spec.getGenesisSpec() .getBellatrixTransitionHelpers() .orElseThrow() - .validateMergeBlock(executionLayer, payload, slot); + .validateMergeBlock(payload, slot); } private void assertPayloadResultStatus( diff --git a/ethereum/statetransition/src/integration-test/java/tech/pegasys/teku/statetransition/attestation/AttestationManagerIntegrationTest.java b/ethereum/statetransition/src/integration-test/java/tech/pegasys/teku/statetransition/attestation/AttestationManagerIntegrationTest.java index dddd5fc0d34..c9a5fe42db7 100644 --- a/ethereum/statetransition/src/integration-test/java/tech/pegasys/teku/statetransition/attestation/AttestationManagerIntegrationTest.java +++ b/ethereum/statetransition/src/integration-test/java/tech/pegasys/teku/statetransition/attestation/AttestationManagerIntegrationTest.java @@ -40,7 +40,6 @@ import tech.pegasys.teku.spec.datastructures.operations.SignedAggregateAndProof; import tech.pegasys.teku.spec.datastructures.state.Fork; import tech.pegasys.teku.spec.datastructures.state.ForkInfo; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.generator.AggregateGenerator; import tech.pegasys.teku.statetransition.blobs.BlobSidecarManager; import tech.pegasys.teku.statetransition.forkchoice.ForkChoice; @@ -77,7 +76,7 @@ class AttestationManagerIntegrationTest { new AggregatingAttestationPool( spec, recentChainData, new NoOpMetricsSystem(), DEFAULT_MAXIMUM_ATTESTATION_COUNT); private final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); private final ForkChoice forkChoice = new ForkChoice( spec, diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoicePayloadExecutor.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoicePayloadExecutor.java index 0aef2b68f04..d29ed28164a 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoicePayloadExecutor.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoicePayloadExecutor.java @@ -50,9 +50,7 @@ public static ForkChoicePayloadExecutor create( final SignedBeaconBlock block, final ExecutionLayerChannel executionLayer) { return new ForkChoicePayloadExecutor( - block, - executionLayer, - new MergeTransitionBlockValidator(spec, recentChainData, executionLayer)); + block, executionLayer, new MergeTransitionBlockValidator(spec, recentChainData)); } public SafeFuture getExecutionResult() { diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidator.java index 03d3280d761..c4c69ec5650 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidator.java @@ -30,7 +30,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; import tech.pegasys.teku.spec.datastructures.execution.SlotAndExecutionPayloadSummary; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers; import tech.pegasys.teku.storage.client.RecentChainData; @@ -42,15 +41,10 @@ public class MergeTransitionBlockValidator { private final Spec spec; private final RecentChainData recentChainData; - private final ExecutionLayerChannel executionLayer; - public MergeTransitionBlockValidator( - final Spec spec, - final RecentChainData recentChainData, - final ExecutionLayerChannel executionLayer) { + public MergeTransitionBlockValidator(final Spec spec, final RecentChainData recentChainData) { this.spec = spec; this.recentChainData = recentChainData; - this.executionLayer = executionLayer; } public SafeFuture verifyTransitionBlock( @@ -151,7 +145,7 @@ private SafeFuture verifyTransitionPayload( new IllegalStateException( "Attempting to validate a bellatrix block when spec does not have bellatrix transition helpers")); return bellatrixTransitionHelpers - .validateMergeBlock(executionLayer, executionPayload, slot) + .validateMergeBlock(executionPayload, slot) .exceptionally( error -> { LOG.error("Error while validating merge block", error); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitor.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitor.java index 952a1362cc5..1796f36ce16 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitor.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitor.java @@ -14,18 +14,14 @@ package tech.pegasys.teku.statetransition.forkchoice; import java.time.Duration; -import java.time.Instant; -import java.util.ArrayDeque; import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.async.Cancellable; -import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.exceptions.InvalidConfigurationException; import tech.pegasys.teku.infrastructure.logging.EventLogger; -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; @@ -38,15 +34,10 @@ public class TerminalPowBlockMonitor { private static final Logger LOG = LogManager.getLogger(); - // number of samples to average out totalDifficulty - private static final int TD_SAMPLES = 40; - // minimum collected samples required for an accurate estimation - static final int TD_MIN_SAMPLES = 15; - // how many times we produce the event, based on polling period (secondsPerEth1Block) - private static final int ETA_EVENT_FREQUENCY_IN_POLLING_PERIODS = 5; + private static final String TTD_DEPRECATED_MESSAGE = + "Bellatrix transition by terminal total difficulty is no more supported"; private final EventLogger eventLogger; - private final TimeProvider timeProvider; private final ExecutionLayerChannel executionLayer; private final AsyncRunner asyncRunner; private Optional timer = Optional.empty(); @@ -55,31 +46,26 @@ public class TerminalPowBlockMonitor { private final ForkChoiceNotifier forkChoiceNotifier; private Duration pollingPeriod; - private int pollingCounter = 0; - private Optional maybeBlockHashTracking = Optional.empty(); + private Optional blockHashTracking = Optional.empty(); private Optional foundTerminalBlockHash = Optional.empty(); private SpecConfigBellatrix specConfigBellatrix; private boolean isBellatrixActive = false; private boolean inSync = true; - private final ArrayDeque lastPowBlocks = new ArrayDeque<>(); - public TerminalPowBlockMonitor( final ExecutionLayerChannel executionLayer, final Spec spec, final RecentChainData recentChainData, final ForkChoiceNotifier forkChoiceNotifier, final AsyncRunner asyncRunner, - final EventLogger eventLogger, - final TimeProvider timeProvider) { + final EventLogger eventLogger) { this.executionLayer = executionLayer; this.asyncRunner = asyncRunner; this.spec = spec; this.recentChainData = recentChainData; this.forkChoiceNotifier = forkChoiceNotifier; this.eventLogger = eventLogger; - this.timeProvider = timeProvider; } public synchronized void start() { @@ -120,9 +106,6 @@ public synchronized boolean isRunning() { } public synchronized void onNodeSyncStateChanged(final boolean inSync) { - if (!this.inSync && inSync) { - lastPowBlocks.clear(); - } this.inSync = inSync; } @@ -135,8 +118,6 @@ private synchronized void monitor() { } } - pollingCounter++; - if (isMergeTransitionComplete(recentChainData.getChainHead())) { LOG.debug("MERGE is completed."); stop(); @@ -148,8 +129,11 @@ private synchronized void monitor() { return; } - maybeBlockHashTracking.ifPresentOrElse( - this::checkTerminalBlockByBlockHash, this::checkTerminalBlockByTTD); + blockHashTracking.ifPresentOrElse( + this::checkTerminalBlockByBlockHash, + () -> { + throw new InvalidConfigurationException(TTD_DEPRECATED_MESSAGE); + }); } private Boolean isMergeTransitionComplete(final Optional chainHead) { @@ -180,12 +164,9 @@ private void initMergeState() { } if (specConfigBellatrix.getTerminalBlockHash().isZero()) { - maybeBlockHashTracking = Optional.empty(); - LOG.debug( - "Enabling tracking by Block Total Difficulty {}", - specConfigBellatrix.getTerminalTotalDifficulty()); + throw new InvalidConfigurationException(TTD_DEPRECATED_MESSAGE); } else { - maybeBlockHashTracking = Optional.of(specConfigBellatrix.getTerminalBlockHash()); + blockHashTracking = Optional.of(specConfigBellatrix.getTerminalBlockHash()); LOG.debug( "Enabling tracking by Block Hash {} and Activation Epoch {}", specConfigBellatrix.getTerminalBlockHash(), @@ -230,132 +211,6 @@ private void checkTerminalBlockByBlockHash(final Bytes32 blockHashTracking) { } } - private void checkTerminalBlockByTTD() { - executionLayer - .eth1GetPowChainHead() - .thenCompose( - powBlock -> { - if (powBlock == null) { - LOG.debug("checkTerminalBlockByTTD: Not checking - Latest pow block is null"); - return SafeFuture.COMPLETE; - } - final UInt256 totalDifficulty = powBlock.getTotalDifficulty(); - if (totalDifficulty.compareTo(specConfigBellatrix.getTerminalTotalDifficulty()) < 0) { - LOG.trace("checkTerminalBlockByTTD: Total Terminal Difficulty not reached."); - try { - checkTtdEta(powBlock); - } catch (Exception ex) { - LOG.debug("TTD ETA calculation exception", ex); - } - - return SafeFuture.COMPLETE; - } - if (powBlock.getBlockTimestamp().isGreaterThan(timeProvider.getTimeInSeconds())) { - LOG.trace("checkTerminalBlockByTTD: Chain head is in the future, ignoring for now"); - return SafeFuture.COMPLETE; - } - - // TTD is reached - if (notYetFound(powBlock.getBlockHash())) { - LOG.trace("checkTerminalBlockByTTD: Terminal Block found!"); - return validateTerminalBlockParentByTTD(powBlock) - .thenAccept( - valid -> { - if (valid) { - LOG.trace( - "Total Difficulty of Terminal Block parent has been validated."); - onTerminalPowBlockFound(powBlock.getBlockHash()); - } else { - LOG.warn( - "A candidate Terminal Block has been found but its parent has a Total Difficulty greater than terminal total difficulty. " - + "It is likely the Terminal Block has been already chosen by the network and The Merge will complete shortly."); - } - }); - } - return SafeFuture.COMPLETE; - }) - .finish(error -> LOG.error("Unexpected error while checking TTD", error)); - } - - private SafeFuture validateTerminalBlockParentByTTD(final PowBlock terminalBlock) { - // if it's genesis validate fast way - if (terminalBlock.getParentHash().isZero()) { - return SafeFuture.completedFuture(true); - } - return executionLayer - .eth1GetPowBlock(terminalBlock.getParentHash()) - .thenApply( - powBlock -> { - UInt256 parentTotalDifficulty = - powBlock - .orElseThrow( - () -> new IllegalStateException("Terminal Block Parent not found!")) - .getTotalDifficulty(); - return parentTotalDifficulty.lessThan( - specConfigBellatrix.getTerminalTotalDifficulty()); - }); - } - - private synchronized void checkTtdEta(final PowBlock currentHead) { - lastPowBlocks.addFirst(currentHead); - if (lastPowBlocks.size() > TD_SAMPLES) { - lastPowBlocks.removeLast(); - } - - if (!inSync - || lastPowBlocks.size() < TD_MIN_SAMPLES - || pollingCounter % ETA_EVENT_FREQUENCY_IN_POLLING_PERIODS != 0) { - return; - } - - final PowBlock latestBlock = lastPowBlocks.getFirst(); - final PowBlock oldestBlock = lastPowBlocks.getLast(); - - final UInt256 timeFrameInSeconds = - UInt256.valueOf( - latestBlock.getBlockTimestamp().minus(oldestBlock.getBlockTimestamp()).longValue()); - // Make sure we don't just have the same block multiple times. - if (timeFrameInSeconds.isZero()) { - return; - } - final UInt256 averageTdPerSeconds = - lastPowBlocks - .getFirst() - .getTotalDifficulty() - .subtract(lastPowBlocks.getLast().getTotalDifficulty()) - .divide(timeFrameInSeconds); - - if (averageTdPerSeconds.isZero()) { - return; - } - - final long now = timeProvider.getTimeInSeconds().longValue(); - - final UInt256 secondsToTTD = - specConfigBellatrix - .getTerminalTotalDifficulty() - .subtract(latestBlock.getTotalDifficulty()) - .divide(averageTdPerSeconds); - - // avoid negative time diff due to time discrepancy with EL - final UInt256 timeDiff = - UInt256.valueOf(Math.max(0, now - latestBlock.getBlockTimestamp().longValue())); - - final long secondsToTTDAdjusted; - // by subtracting timeDiff we could go after the merge and get negative result, - // let's avoid that. - if (secondsToTTD.greaterThan(timeDiff)) { - secondsToTTDAdjusted = secondsToTTD.subtract(timeDiff).toLong(); - } else { - secondsToTTDAdjusted = 0L; - } - - final Duration eta = Duration.ofSeconds(secondsToTTDAdjusted); - final Instant etaInstant = Instant.ofEpochSecond(now + secondsToTTDAdjusted); - - eventLogger.terminalPowBlockTtdEta(latestBlock.getTotalDifficulty(), eta, etaInstant); - } - private void onTerminalPowBlockFound(final Bytes32 blockHash) { foundTerminalBlockHash = Optional.of(blockHash); forkChoiceNotifier.onTerminalBlockReached(blockHash); diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockImporterTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockImporterTest.java index cc6e36ca465..b081353324b 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockImporterTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockImporterTest.java @@ -96,7 +96,7 @@ public class BlockImporterTest { mock(WeakSubjectivityValidator.class); private final ForkChoiceNotifier forkChoiceNotifier = new NoopForkChoiceNotifier(); private final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(spec, recentChainData); private final MetricsSystem metricsSystem = new StubMetricsSystem(); private final ForkChoice forkChoice = diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockManagerTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockManagerTest.java index daf13b3633f..caa47ce700c 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockManagerTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/block/BlockManagerTest.java @@ -79,7 +79,6 @@ import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; import tech.pegasys.teku.spec.datastructures.blocks.SlotAndBlockRoot; import tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; import tech.pegasys.teku.spec.generator.ChainBuilder.BlockOptions; @@ -182,8 +181,7 @@ private void setupWithSpec(final Spec spec) { spec, historicalBlockTolerance, futureBlockTolerance, maxPendingBlocks); this.localChain = InMemoryStorageSystemBuilder.buildDefault(spec); this.localRecentChainData = localChain.recentChainData(); - this.transitionBlockValidator = - new MergeTransitionBlockValidator(spec, localRecentChainData, ExecutionLayerChannel.NOOP); + this.transitionBlockValidator = new MergeTransitionBlockValidator(spec, localRecentChainData); this.forkChoice = new ForkChoice( spec, diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceTest.java index 589b3b0e151..9f4503de388 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/ForkChoiceTest.java @@ -41,7 +41,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -1224,19 +1223,11 @@ private void doMerge(final boolean optimistic) { } private SignedBlockAndState generateMergeBlock() { - final UInt256 terminalTotalDifficulty = - spec.getGenesisSpecConfig().toVersionBellatrix().orElseThrow().getTerminalTotalDifficulty(); final Bytes32 terminalBlockHash = dataStructureUtil.randomBytes32(); final Bytes32 terminalBlockParentHash = dataStructureUtil.randomBytes32(); - final PowBlock terminalBlock = - new PowBlock( - terminalBlockHash, terminalBlockParentHash, terminalTotalDifficulty.plus(1), ZERO); + final PowBlock terminalBlock = new PowBlock(terminalBlockHash, terminalBlockParentHash, ZERO); final PowBlock terminalParentBlock = - new PowBlock( - terminalBlockParentHash, - dataStructureUtil.randomBytes32(), - terminalTotalDifficulty.subtract(1), - ZERO); + new PowBlock(terminalBlockParentHash, dataStructureUtil.randomBytes32(), ZERO); executionLayer.addPowBlock(terminalBlock); executionLayer.addPowBlock(terminalParentBlock); return chainBuilder.generateBlockAtSlot( diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidatorTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidatorTest.java index f90a7af5e3b..ebade0712ef 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidatorTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/MergeTransitionBlockValidatorTest.java @@ -19,7 +19,6 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -31,8 +30,6 @@ 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.datastructures.execution.ExecutionPayload; -import tech.pegasys.teku.spec.datastructures.execution.PowBlock; import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.bellatrix.BeaconStateBellatrix; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; @@ -46,7 +43,15 @@ class MergeTransitionBlockValidatorTest { - private final Spec spec = TestSpecFactory.createMinimalBellatrix(); + private final Bytes32 terminalBlockHash = Bytes32.random(); + private final UInt64 terminalEpoch = UInt64.ZERO; + private final Spec spec = + TestSpecFactory.createMinimalBellatrix( + b -> + b.bellatrixBuilder( + bb -> + bb.terminalBlockHash(terminalBlockHash) + .terminalBlockHashActivationEpoch(terminalEpoch))); private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); private final ExecutionLayerChannelStub executionLayer = new ExecutionLayerChannelStub(spec, false, Optional.empty()); @@ -79,7 +84,7 @@ void setUp() { @Test void shouldReturnValidImmediatelyWhenThereIsTransitionBlockFullyVerified() { - final SignedBlockAndState chainHead = generateNonfinalizedTransition(); + final SignedBlockAndState chainHead = generateNonfinalizedTransition(true); storageSystem.chainUpdater().saveBlock(chainHead); final SignedBlockAndState blockToVerify = storageSystem.chainBuilder().generateNextBlock(); @@ -109,10 +114,9 @@ void shouldReturnValidImmediatelyWhenThereIsTransitionBlockFullyVerified() { @Test void shouldVerifyNonFinalizedAncestorTransitionBlock() { - final SignedBlockAndState transitionBlock = generateNonfinalizedTransition(); + final SignedBlockAndState transitionBlock = generateNonfinalizedTransition(true); final SignedBlockAndState chainHead = storageSystem.chainBuilder().getLatestBlockAndState(); final SignedBlockAndState blockToVerify = storageSystem.chainBuilder().generateNextBlock(); - withValidTransitionBlock(transitionBlock); final MergeTransitionBlockValidator transitionVerifier = createTransitionValidator(); @@ -133,8 +137,6 @@ void shouldVerifyNonFinalizedAncestorTransitionBlock() { .getLatestExecutionPayloadHeader(), blockToVerify.getBlock()); - assertThat(executionLayer.getRequestedPowBlocks()) - .contains(getExecutionPayload(transitionBlock).getParentHash()); assertThat(result) .isCompletedWithValue( new PayloadValidationResult(transitionBlock.getRoot(), PayloadStatus.VALID)); @@ -142,10 +144,9 @@ void shouldVerifyNonFinalizedAncestorTransitionBlock() { @Test void shouldReportRootForInvalidNonFinalizedAncestorTransitionBlock() { - final SignedBlockAndState transitionBlock = generateNonfinalizedTransition(); + final SignedBlockAndState transitionBlock = generateNonfinalizedTransition(false); final SignedBlockAndState chainHead = storageSystem.chainBuilder().getLatestBlockAndState(); final SignedBlockAndState blockToVerify = storageSystem.chainBuilder().generateNextBlock(); - withInvalidTransitionBlock(transitionBlock); final MergeTransitionBlockValidator transitionVerifier = createTransitionValidator(); @@ -166,8 +167,6 @@ void shouldReportRootForInvalidNonFinalizedAncestorTransitionBlock() { .getLatestExecutionPayloadHeader(), blockToVerify.getBlock()); - assertThat(executionLayer.getRequestedPowBlocks()) - .contains(getExecutionPayload(transitionBlock).getParentHash()); assertThat(result).isCompleted(); final PayloadValidationResult validationResult = safeJoin(result); assertThat(validationResult.getInvalidTransitionBlockRoot()) @@ -177,7 +176,7 @@ void shouldReportRootForInvalidNonFinalizedAncestorTransitionBlock() { @Test void shouldVerifyFinalizedAncestorTransitionBlock() { - final SignedBlockAndState transitionBlock = generateFinalizedTransition(); + generateFinalizedTransition(true); final BeaconStateBellatrix chainHeadState = storageSystem .chainBuilder() @@ -185,7 +184,6 @@ void shouldVerifyFinalizedAncestorTransitionBlock() { .getState() .toVersionBellatrix() .orElseThrow(); - withValidTransitionBlock(transitionBlock); final SignedBlockAndState blockToVerify = storageSystem.chainBuilder().generateNextBlock(); @@ -198,8 +196,6 @@ void shouldVerifyFinalizedAncestorTransitionBlock() { transitionVerifier.verifyTransitionBlock( chainHeadState.getLatestExecutionPayloadHeader(), blockToVerify.getBlock()); - assertThat(executionLayer.getRequestedPowBlocks()) - .contains(getExecutionPayload(transitionBlock).getParentHash()); assertThat(result).isCompletedWithValue(new PayloadValidationResult(PayloadStatus.VALID)); } @@ -210,7 +206,7 @@ void shouldVerifyFinalizedAncestorTransitionBlock() { */ @Test void shouldFailWithFatalServiceFailuresExceptionWhenFinalizedAncestorTransitionBlockIsInvalid() { - final SignedBlockAndState transitionBlock = generateFinalizedTransition(); + generateFinalizedTransition(false); final BeaconStateBellatrix chainHeadState = storageSystem .chainBuilder() @@ -218,7 +214,6 @@ void shouldFailWithFatalServiceFailuresExceptionWhenFinalizedAncestorTransitionB .getState() .toVersionBellatrix() .orElseThrow(); - withInvalidTransitionBlock(transitionBlock); final SignedBlockAndState blockToVerify = storageSystem.chainBuilder().generateNextBlock(); @@ -234,51 +229,19 @@ void shouldFailWithFatalServiceFailuresExceptionWhenFinalizedAncestorTransitionB assertThatSafeFuture(result).isCompletedExceptionallyWith(FatalServiceFailureException.class); } - private void withValidTransitionBlock(final SignedBlockAndState transitionBlock) { - final UInt256 ttd = - spec.getGenesisSpecConfig().toVersionBellatrix().orElseThrow().getTerminalTotalDifficulty(); - final UInt256 terminalBlockDifficulty = ttd.plus(1); - final UInt256 ttdBlockParentDifficulty = ttd.subtract(1); - withPowBlockDifficulties(transitionBlock, terminalBlockDifficulty, ttdBlockParentDifficulty); - } - - private void withInvalidTransitionBlock(final SignedBlockAndState transitionBlock) { - final UInt256 ttd = - spec.getGenesisSpecConfig().toVersionBellatrix().orElseThrow().getTerminalTotalDifficulty(); - final UInt256 terminalBlockDifficulty = ttd.subtract(1); - final UInt256 ttdBlockParentDifficulty = ttd.subtract(2); - withPowBlockDifficulties(transitionBlock, terminalBlockDifficulty, ttdBlockParentDifficulty); - } - - private void withPowBlockDifficulties( - final SignedBlockAndState transitionBlock, - final UInt256 terminalBlockDifficulty, - final UInt256 ttdBlockParentDifficulty) { - final Bytes32 terminalBlockParentHash = dataStructureUtil.randomBytes32(); - executionLayer.addPowBlock( - new PowBlock( - getExecutionPayload(transitionBlock).getParentHash(), - terminalBlockParentHash, - terminalBlockDifficulty, - UInt64.ZERO)); - executionLayer.addPowBlock( - new PowBlock( - terminalBlockParentHash, - dataStructureUtil.randomBytes32(), - ttdBlockParentDifficulty, - UInt64.ZERO)); - } - - private SignedBlockAndState generateNonfinalizedTransition() { + private SignedBlockAndState generateNonfinalizedTransition(final boolean isValid) { storageSystem .chainBuilder() .generateBlocksUpToSlot(5) .forEach(storageSystem.chainUpdater()::saveOptimisticBlock); - final Bytes32 terminalBlockHash = dataStructureUtil.randomBytes32(); final SignedBlockAndState transitionBlock = storageSystem .chainBuilder() - .generateBlockAtSlot(6, BlockOptions.create().setTerminalBlockHash(terminalBlockHash)); + .generateBlockAtSlot( + 6, + BlockOptions.create() + .setTerminalBlockHash( + isValid ? terminalBlockHash : dataStructureUtil.randomBytes32())); storageSystem.chainUpdater().saveOptimisticBlock(transitionBlock); storageSystem @@ -290,24 +253,14 @@ private SignedBlockAndState generateNonfinalizedTransition() { return transitionBlock; } - private SignedBlockAndState generateFinalizedTransition() { - final SignedBlockAndState transitionBlock = generateNonfinalizedTransition(); + private void generateFinalizedTransition(final boolean isValid) { + generateNonfinalizedTransition(isValid); // Finalize between transition block and chain head storageSystem.chainUpdater().finalizeEpoch(1); - return transitionBlock; - } - - private ExecutionPayload getExecutionPayload(final SignedBlockAndState blockToVerify) { - return blockToVerify - .getBlock() - .getMessage() - .getBody() - .getOptionalExecutionPayload() - .orElseThrow(); } private MergeTransitionBlockValidator createTransitionValidator() { - return new MergeTransitionBlockValidator(spec, storageSystem.recentChainData(), executionLayer); + return new MergeTransitionBlockValidator(spec, storageSystem.recentChainData()); } } diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitorTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitorTest.java index 08f55709b27..a6da2897cf2 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitorTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/forkchoice/TerminalPowBlockMonitorTest.java @@ -22,10 +22,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static tech.pegasys.teku.infrastructure.async.SafeFuture.completedFuture; -import static tech.pegasys.teku.statetransition.forkchoice.TerminalPowBlockMonitor.TD_MIN_SAMPLES; -import java.time.Duration; -import java.time.Instant; import java.util.Optional; import java.util.function.Consumer; import org.apache.tuweni.bytes.Bytes32; @@ -115,13 +112,7 @@ private void setUpCommon(final Consumer bellatrixBuilder) { terminalPowBlockMonitor = new TerminalPowBlockMonitor( - executionLayer, - spec, - recentChainData, - forkChoiceNotifier, - asyncRunner, - eventLogger, - timeProvider); + executionLayer, spec, recentChainData, forkChoiceNotifier, asyncRunner, eventLogger); terminalPowBlockMonitor.onNodeSyncStateChanged(true); } @@ -158,16 +149,13 @@ void shouldNotFailWhenCurrentSlotInBellatrixMilestoneButHeadStateIsFromEarlierMi final Bytes32 headBlockParentHash = dataStructureUtil.randomBytes32(); when(executionLayer.eth1GetPowChainHead()) .thenReturn( - completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TTD, TIME_IN_PAST))); + completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TIME_IN_PAST))); when(executionLayer.eth1GetPowBlock(headBlockParentHash)) .thenReturn( completedFuture( Optional.of( new PowBlock( - headBlockParentHash, - dataStructureUtil.randomBytes32(), - TTD.subtract(10), - TIME_IN_PAST)))); + headBlockParentHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); terminalPowBlockMonitor.start(); @@ -203,11 +191,7 @@ public void shouldPerformTerminalBlockDetectionByTTD() { when(executionLayer.eth1GetPowChainHead()) .thenReturn( completedFuture( - new PowBlock( - headBlockHash, - dataStructureUtil.randomBytes32(), - TTD.subtract(10), - TIME_IN_PAST))); + new PowBlock(headBlockHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST))); asyncRunner.executeQueuedActions(); @@ -219,16 +203,13 @@ public void shouldPerformTerminalBlockDetectionByTTD() { headBlockParentHash = dataStructureUtil.randomBytes32(); when(executionLayer.eth1GetPowChainHead()) .thenReturn( - completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TTD, TIME_IN_PAST))); + completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TIME_IN_PAST))); when(executionLayer.eth1GetPowBlock(headBlockParentHash)) .thenReturn( completedFuture( Optional.of( new PowBlock( - headBlockParentHash, - dataStructureUtil.randomBytes32(), - TTD.subtract(10), - TIME_IN_PAST)))); + headBlockParentHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); asyncRunner.executeQueuedActions(); @@ -248,17 +229,13 @@ public void shouldPerformTerminalBlockDetectionByTTD() { headBlockParentHash = dataStructureUtil.randomBytes32(); when(executionLayer.eth1GetPowChainHead()) .thenReturn( - completedFuture( - new PowBlock(headBlockHash, headBlockParentHash, TTD.add(10), TIME_IN_PAST))); + completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TIME_IN_PAST))); when(executionLayer.eth1GetPowBlock(headBlockParentHash)) .thenReturn( completedFuture( Optional.of( new PowBlock( - headBlockParentHash, - dataStructureUtil.randomBytes32(), - TTD, - TIME_IN_PAST)))); + headBlockParentHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); asyncRunner.executeQueuedActions(); @@ -271,17 +248,13 @@ public void shouldPerformTerminalBlockDetectionByTTD() { headBlockParentHash = dataStructureUtil.randomBytes32(); when(executionLayer.eth1GetPowChainHead()) .thenReturn( - completedFuture( - new PowBlock(headBlockHash, headBlockParentHash, TTD.add(10), TIME_IN_PAST))); + completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TIME_IN_PAST))); when(executionLayer.eth1GetPowBlock(headBlockParentHash)) .thenReturn( completedFuture( Optional.of( new PowBlock( - headBlockParentHash, - dataStructureUtil.randomBytes32(), - TTD.subtract(10), - TIME_IN_PAST)))); + headBlockParentHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); asyncRunner.executeQueuedActions(); @@ -315,16 +288,13 @@ public void shouldNotSelectTTDBlockWithTimestampInFuture() { final UInt64 timeInFuture = timeProvider.getTimeInSeconds().plus(1); when(executionLayer.eth1GetPowChainHead()) .thenReturn( - completedFuture(new PowBlock(headBlockHash, headBlockParentHash, TTD, timeInFuture))); + completedFuture(new PowBlock(headBlockHash, headBlockParentHash, timeInFuture))); when(executionLayer.eth1GetPowBlock(headBlockParentHash)) .thenReturn( completedFuture( Optional.of( new PowBlock( - headBlockParentHash, - dataStructureUtil.randomBytes32(), - TTD.subtract(10), - TIME_IN_PAST)))); + headBlockParentHash, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); asyncRunner.executeQueuedActions(); @@ -388,10 +358,7 @@ void shouldPerformTerminalBlockDetectionByTerminalBlockHash() { completedFuture( Optional.of( new PowBlock( - TERMINAL_BLOCK_HASH, - dataStructureUtil.randomBytes32(), - UInt256.ONE, - TIME_IN_PAST)))); + TERMINAL_BLOCK_HASH, dataStructureUtil.randomBytes32(), TIME_IN_PAST)))); asyncRunner.executeQueuedActions(); @@ -436,61 +403,4 @@ void shouldNotPerformCheckIfSyncing() { verifyNoMoreInteractions(executionLayer); } - - @Test - void shouldCalculateTtdEta() { - - setUpTTDConfig(); - - final UInt256 tdDiff = TTD.divide(TD_MIN_SAMPLES * 2); - - terminalPowBlockMonitor.start(); - - goToSlot(BELLATRIX_FORK_EPOCH.times(spec.getGenesisSpecConfig().getSlotsPerEpoch())); - - UInt256 lastTD = UInt256.ZERO; - UInt64 lastTime = UInt64.ZERO; - - for (int cnt = TD_MIN_SAMPLES; cnt > 0; cnt--) { - lastTD = lastTD.plus(tdDiff); - lastTime = timeProvider.getTimeInSeconds(); - pollTtd(lastTD, lastTime); - timeProvider.advanceTimeBySeconds(spec.getGenesisSpecConfig().getSecondsPerEth1Block()); - } - - final long eta = (long) spec.getGenesisSpecConfig().getSecondsPerEth1Block() * TD_MIN_SAMPLES; - final Duration expectedETA = Duration.ofSeconds(eta); - final Instant expectedInstant = Instant.ofEpochSecond(eta + lastTime.longValue()); - - verify(eventLogger).terminalPowBlockTtdEta(lastTD, expectedETA, expectedInstant); - - // check that if current time goes beyond the ETA we get an event with NOW values - timeProvider.advanceTimeBySeconds(eta + 100); - - pollTtd(lastTD, lastTime); - pollTtd(lastTD, lastTime); - pollTtd(lastTD, lastTime); - pollTtd(lastTD, lastTime); - pollTtd(lastTD, lastTime); - - verify(eventLogger) - .terminalPowBlockTtdEta( - lastTD, - Duration.ZERO, - Instant.ofEpochSecond(timeProvider.getTimeInSeconds().longValue())); - - verifyNoMoreInteractions(eventLogger); - } - - private void pollTtd(final UInt256 ttd, final UInt64 time) { - when(executionLayer.eth1GetPowChainHead()) - .thenReturn( - completedFuture( - new PowBlock( - dataStructureUtil.randomBytes32(), - dataStructureUtil.randomBytes32(), - ttd, - time))); - asyncRunner.executeQueuedActions(); - } } diff --git a/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/BeaconChainUtil.java b/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/BeaconChainUtil.java index 55cc8d459cc..b29344ffe1d 100644 --- a/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/BeaconChainUtil.java +++ b/ethereum/statetransition/src/testFixtures/java/tech/pegasys/teku/statetransition/BeaconChainUtil.java @@ -40,7 +40,6 @@ import tech.pegasys.teku.spec.datastructures.operations.Deposit; import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; import tech.pegasys.teku.spec.generator.BlockProposalTestUtil; import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; @@ -108,7 +107,7 @@ public static BeaconChainUtil create( storageClient, BlobSidecarManager.NOOP, new NoopForkChoiceNotifier(), - new MergeTransitionBlockValidator(spec, storageClient, ExecutionLayerChannel.NOOP), + new MergeTransitionBlockValidator(spec, storageClient), new StubMetricsSystem()), true); } @@ -128,7 +127,7 @@ public static BeaconChainUtil create( storageClient, BlobSidecarManager.NOOP, new NoopForkChoiceNotifier(), - new MergeTransitionBlockValidator(spec, storageClient, ExecutionLayerChannel.NOOP), + new MergeTransitionBlockValidator(spec, storageClient), new StubMetricsSystem()), signDeposits); } @@ -324,8 +323,7 @@ public BeaconChainUtil build() { recentChainData, BlobSidecarManager.NOOP, new NoopForkChoiceNotifier(), - new MergeTransitionBlockValidator( - spec, recentChainData, ExecutionLayerChannel.NOOP), + new MergeTransitionBlockValidator(spec, recentChainData), new StubMetricsSystem()); } if (validatorKeys == null) { diff --git a/fork-choice-tests/src/integration-test/java/tech/pegasys/teku/forkChoiceTests/ForkChoiceIntegrationTest.java b/fork-choice-tests/src/integration-test/java/tech/pegasys/teku/forkChoiceTests/ForkChoiceIntegrationTest.java index ec9cb09f9ce..16270f33f6c 100644 --- a/fork-choice-tests/src/integration-test/java/tech/pegasys/teku/forkChoiceTests/ForkChoiceIntegrationTest.java +++ b/fork-choice-tests/src/integration-test/java/tech/pegasys/teku/forkChoiceTests/ForkChoiceIntegrationTest.java @@ -48,7 +48,6 @@ import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconStateSchema; import tech.pegasys.teku.spec.datastructures.util.AttestationProcessingResult; -import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannel; import tech.pegasys.teku.spec.executionlayer.ExecutionLayerChannelStub; import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; import tech.pegasys.teku.spec.schemas.SchemaDefinitions; @@ -183,7 +182,7 @@ void runForkChoiceTests( final InlineEventThread forkChoiceExecutor = new InlineEventThread(); final MergeTransitionBlockValidator transitionBlockValidator = - new MergeTransitionBlockValidator(SPEC, storageClient, ExecutionLayerChannel.NOOP); + new MergeTransitionBlockValidator(SPEC, storageClient); ForkChoice forkChoice = new ForkChoice( SPEC, 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 90508b0303b..6de4dfd31b6 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 @@ -611,8 +611,7 @@ protected void initMergeMonitors() { recentChainData, forkChoiceNotifier, beaconAsyncRunner, - EVENT_LOG, - timeProvider)); + EVENT_LOG)); } } @@ -822,7 +821,7 @@ protected void initForkChoice() { forkChoiceNotifier, forkChoiceStateProvider, new TickProcessor(spec, recentChainData), - new MergeTransitionBlockValidator(spec, recentChainData, executionLayer), + new MergeTransitionBlockValidator(spec, recentChainData), beaconConfig.eth2NetworkConfig().isForkChoiceLateBlockReorgEnabled(), debugDataDumper, metricsSystem);