diff --git a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactory.java b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactory.java index 3b7ba7c8a0b..20357e8c7c3 100644 --- a/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactory.java +++ b/beacon/validator/src/main/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactory.java @@ -374,11 +374,8 @@ private ExecutionRequests getExecutionRequestsFromBuilderFlow( // from the builder bid .flatMap(BuilderBid::getOptionalExecutionRequests) // from the local fallback - .orElse( - builderBidOrFallbackData - .getFallbackDataRequired() - .getExecutionRequests() - .orElseThrow()); + .or(() -> builderBidOrFallbackData.getFallbackDataRequired().getExecutionRequests()) + .orElseThrow(); } public Consumer createBlockUnblinderSelector( diff --git a/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactoryTest.java b/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactoryTest.java index ac06984d4b9..1370795c08e 100644 --- a/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactoryTest.java +++ b/beacon/validator/src/test/java/tech/pegasys/teku/validator/coordinator/BlockOperationSelectorFactoryTest.java @@ -1020,6 +1020,45 @@ void shouldGetExecutionRequestsForLocallyProducedBlocks() { assertThat(bodyBuilder.executionRequests).isEqualTo(expectedExecutionRequests); } + @Test + void shouldIncludeExecutionRequestsInBlindedBlock() { + final UInt64 slot = UInt64.valueOf(2); + final BeaconState blockSlotState = dataStructureUtil.randomBeaconState(slot); + + final ExecutionRequests executionRequests = dataStructureUtil.randomExecutionRequests(); + + final ExecutionPayloadContext executionPayloadContextWithValidatorRegistration = + dataStructureUtil.randomPayloadExecutionContext(false, true); + when(forkChoiceNotifier.getPayloadId(any(), any())) + .thenReturn( + SafeFuture.completedFuture( + Optional.of(executionPayloadContextWithValidatorRegistration))); + + prepareBlindedBlockWithBlobsAndExecutionRequestsProduction( + dataStructureUtil.randomExecutionPayloadHeader(), + executionPayloadContextWithValidatorRegistration, + blockSlotState, + dataStructureUtil.randomBlobKzgCommitments(), + executionRequests, + dataStructureUtil.randomUInt256()); + + final CapturingBeaconBlockBodyBuilder bodyBuilder = + new CapturingBeaconBlockBodyBuilder(true, true); + + safeJoin( + factory + .createSelector( + parentRoot, + blockSlotState, + dataStructureUtil.randomSignature(), + Optional.empty(), + Optional.empty(), + BlockProductionPerformance.NOOP) + .apply(bodyBuilder)); + + assertThat(bodyBuilder.executionRequests).isEqualTo(executionRequests); + } + private void prepareBlockProductionWithPayload( final ExecutionPayload executionPayload, final ExecutionPayloadContext executionPayloadContext, @@ -1158,6 +1197,33 @@ private void prepareBlindedBlockAndBlobsProduction( executionPayloadContext, SafeFuture.completedFuture(builderBidOrFallbackData))); } + private void prepareBlindedBlockWithBlobsAndExecutionRequestsProduction( + final ExecutionPayloadHeader executionPayloadHeader, + final ExecutionPayloadContext executionPayloadContext, + final BeaconState blockSlotState, + final SszList blobKzgCommitments, + final ExecutionRequests executionRequests, + final UInt256 executionPayloadValue) { + final BuilderBidOrFallbackData builderBidOrFallbackData = + BuilderBidOrFallbackData.create( + dataStructureUtil.randomBuilderBid( + builder -> { + builder.header(executionPayloadHeader); + builder.blobKzgCommitments(blobKzgCommitments); + builder.executionRequests(executionRequests); + builder.value(executionPayloadValue); + })); + when(executionLayer.initiateBlockProduction( + executionPayloadContext, + blockSlotState, + true, + Optional.empty(), + BlockProductionPerformance.NOOP)) + .thenReturn( + ExecutionPayloadResult.createForBuilderFlow( + executionPayloadContext, SafeFuture.completedFuture(builderBidOrFallbackData))); + } + private void prepareBlindedBlockAndBlobsProductionWithFallBack( final ExecutionPayload executionPayload, final ExecutionPayloadContext executionPayloadContext, diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidBuilderElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidBuilderElectra.java index be9c7bbb53f..6f52613f3ce 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidBuilderElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidBuilderElectra.java @@ -53,6 +53,6 @@ public BuilderBid build() { @Override protected void validate() { super.validate(); - checkNotNull(blobKzgCommitments, "blobKzgCommitments must be specified"); + checkNotNull(executionRequests, "executionRequests must be specified"); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectraImpl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectraImpl.java index 7299d8edd44..9a5d2541d5a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectraImpl.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectraImpl.java @@ -13,7 +13,6 @@ package tech.pegasys.teku.spec.datastructures.builder.versions.electra; -import java.util.Optional; import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.bls.BLSPublicKey; import tech.pegasys.teku.infrastructure.ssz.SszList; @@ -54,11 +53,6 @@ public ExecutionPayloadHeader getHeader() { return getField0(); } - @Override - public Optional getOptionalExecutionRequests() { - return Optional.empty(); - } - @Override public SszList getBlobKzgCommitments() { return getField1(); diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index eb36f99fe43..55ca1200742 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -636,6 +636,9 @@ public BuilderBid randomBuilderBid(final Consumer builderModi schemaDefinitions .toVersionDeneb() .ifPresent(__ -> builder.blobKzgCommitments(randomBlobKzgCommitments())); + schemaDefinitions + .toVersionElectra() + .ifPresent(__ -> builder.executionRequests(randomExecutionRequests())); // 1 ETH is 10^18 wei, Uint256 max is more than 10^77, so just to avoid // overflows in // computation