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 7b2de4e9f92..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 @@ -347,21 +347,35 @@ private SafeFuture setExecutionRequests( if (!bodyBuilder.supportsExecutionRequests()) { return SafeFuture.COMPLETE; } - - final SafeFuture executionRequestsFuture; + final SafeFuture executionRequests; if (executionPayloadResult.isFromLocalFlow()) { - executionRequestsFuture = + // local, non-blinded flow + executionRequests = executionPayloadResult - .getExecutionRequestsFromLocalFlow() + .getExecutionRequestsFutureFromLocalFlow() .orElseThrow() .thenApply(Optional::orElseThrow); } else { - // TODO Add support for builder flow in Electra - // (https://github.com/Consensys/teku/issues/8624) - executionRequestsFuture = SafeFuture.completedFuture(null); + // builder, blinded flow + executionRequests = + executionPayloadResult + .getBuilderBidOrFallbackDataFuture() + .orElseThrow() + .thenApply(this::getExecutionRequestsFromBuilderFlow); } - return executionRequestsFuture.thenAccept(bodyBuilder::executionRequests); + return executionRequests.thenAccept(bodyBuilder::executionRequests); + } + + private ExecutionRequests getExecutionRequestsFromBuilderFlow( + final BuilderBidOrFallbackData builderBidOrFallbackData) { + return builderBidOrFallbackData + .getBuilderBid() + // from the builder bid + .flatMap(BuilderBid::getOptionalExecutionRequests) + // from the local fallback + .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/data/serializer/src/main/java/tech/pegasys/teku/api/schema/electra/BlindedBeaconBlockBodyElectra.java b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/electra/BlindedBeaconBlockBodyElectra.java index 2e61c080721..8623b4d4855 100644 --- a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/electra/BlindedBeaconBlockBodyElectra.java +++ b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/electra/BlindedBeaconBlockBodyElectra.java @@ -14,11 +14,9 @@ package tech.pegasys.teku.api.schema.electra; import static com.google.common.base.Preconditions.checkNotNull; -import static tech.pegasys.teku.api.schema.SchemaConstants.DESCRIPTION_BYTES32; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; import org.apache.tuweni.bytes.Bytes32; import tech.pegasys.teku.api.schema.Attestation; @@ -39,6 +37,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BlindedBeaconBlockBodySchemaElectra; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsSchema; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; public class BlindedBeaconBlockBodyElectra extends BeaconBlockBodyAltair { @@ -52,9 +51,8 @@ public class BlindedBeaconBlockBodyElectra extends BeaconBlockBodyAltair { @JsonProperty("blob_kzg_commitments") public final List blobKZGCommitments; - @JsonProperty("execution_requests_root") - @Schema(type = "string", format = "byte", description = DESCRIPTION_BYTES32) - public final Bytes32 executionRequestsRoot; + @JsonProperty("execution_requests") + public final ExecutionRequests executionRequests; @JsonCreator public BlindedBeaconBlockBodyElectra( @@ -72,7 +70,7 @@ public BlindedBeaconBlockBodyElectra( @JsonProperty("bls_to_execution_changes") final List blsToExecutionChanges, @JsonProperty("blob_kzg_commitments") final List blobKZGCommitments, - @JsonProperty("execution_requests_root") final Bytes32 executionRequestsRoot) { + @JsonProperty("execution_requests") final ExecutionRequests executionRequests) { super( randaoReveal, eth1Data, @@ -91,9 +89,8 @@ public BlindedBeaconBlockBodyElectra( this.blsToExecutionChanges = blsToExecutionChanges; checkNotNull(blobKZGCommitments, "BlobKZGCommitments is required for Electra blinded blocks"); this.blobKZGCommitments = blobKZGCommitments; - checkNotNull( - executionRequestsRoot, "ExecutionRequestsRoot is required for Electra blinded blocks"); - this.executionRequestsRoot = executionRequestsRoot; + checkNotNull(executionRequests, "ExecutionRequests is required for Electra blinded blocks"); + this.executionRequests = executionRequests; } public BlindedBeaconBlockBodyElectra( @@ -110,9 +107,7 @@ public BlindedBeaconBlockBodyElectra( .map(SszKZGCommitment::getKZGCommitment) .map(KZGCommitment::new) .toList(); - // TODO Electra Builder API changes - // (https://github.com/Consensys/teku/issues/8624) - this.executionRequestsRoot = Bytes32.ZERO; + this.executionRequests = new ExecutionRequests(blockBody.getExecutionRequests()); } @Override @@ -139,6 +134,9 @@ public BeaconBlockBody asInternalBeaconBlockBody(final SpecVersion spec) { final SszListSchema blobKZGCommitmentsSchema = getBeaconBlockBodySchema(spec).getBlobKzgCommitmentsSchema(); + final ExecutionRequestsSchema executionRequestsSchema = + getBeaconBlockBodySchema(spec).getExecutionRequestsSchema(); + return super.asInternalBeaconBlockBody( spec, builder -> { @@ -154,7 +152,8 @@ public BeaconBlockBody asInternalBeaconBlockBody(final SpecVersion spec) { .map(KZGCommitment::asInternalKZGCommitment) .map(SszKZGCommitment::new) .collect(blobKZGCommitmentsSchema.collector())); - // TODO Electra Builder API changes (https://github.com/Consensys/teku/pull/8600) + builder.executionRequests( + this.executionRequests.asInternalConsolidationRequest(executionRequestsSchema)); return SafeFuture.COMPLETE; }); } diff --git a/ethereum/executionclient/src/integration-test/java/tech/pegasys/teku/ethereum/executionclient/rest/RestBuilderClientTest.java b/ethereum/executionclient/src/integration-test/java/tech/pegasys/teku/ethereum/executionclient/rest/RestBuilderClientTest.java index 2481c887066..c7fb14d6100 100644 --- a/ethereum/executionclient/src/integration-test/java/tech/pegasys/teku/ethereum/executionclient/rest/RestBuilderClientTest.java +++ b/ethereum/executionclient/src/integration-test/java/tech/pegasys/teku/ethereum/executionclient/rest/RestBuilderClientTest.java @@ -17,6 +17,7 @@ import static tech.pegasys.teku.spec.SpecMilestone.BELLATRIX; import static tech.pegasys.teku.spec.SpecMilestone.CAPELLA; import static tech.pegasys.teku.spec.SpecMilestone.DENEB; +import static tech.pegasys.teku.spec.SpecMilestone.ELECTRA; import static tech.pegasys.teku.spec.schemas.ApiSchemas.SIGNED_VALIDATOR_REGISTRATIONS_SCHEMA; import com.fasterxml.jackson.core.JsonProcessingException; @@ -60,9 +61,8 @@ import tech.pegasys.teku.spec.networks.Eth2Network; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsBellatrix; -// TODO Re-enable electra as part of https://github.com/Consensys/teku/issues/8624 @TestSpecContext( - milestone = {BELLATRIX, CAPELLA, DENEB}, + milestone = {BELLATRIX, CAPELLA, DENEB, ELECTRA}, network = Eth2Network.MAINNET) class RestBuilderClientTest { diff --git a/ethereum/executionclient/src/integration-test/resources/builder/electra/signedBuilderBid.json b/ethereum/executionclient/src/integration-test/resources/builder/electra/signedBuilderBid.json index e66ce583346..c99ec7d1266 100644 --- a/ethereum/executionclient/src/integration-test/resources/builder/electra/signedBuilderBid.json +++ b/ethereum/executionclient/src/integration-test/resources/builder/electra/signedBuilderBid.json @@ -24,6 +24,31 @@ "blob_kzg_commitments": [ "0xa94170080872584e54a1cf092d845703b13907f2e6b3b1c0ad573b910530499e3bcd48c6378846b80d2bfa58c81cf3d5" ], + "execution_requests": { + "deposits": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "1", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "index": "1" + } + ], + "withdrawals": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "validator_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "amount": "1" + } + ], + "consolidations": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "source_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "target_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + } + ] + }, "value": "1", "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" }, diff --git a/ethereum/executionclient/src/integration-test/resources/builder/electra/unblindedBuilderPayload.json b/ethereum/executionclient/src/integration-test/resources/builder/electra/unblindedBuilderPayload.json index bea8534900b..10fd97ff686 100644 --- a/ethereum/executionclient/src/integration-test/resources/builder/electra/unblindedBuilderPayload.json +++ b/ethereum/executionclient/src/integration-test/resources/builder/electra/unblindedBuilderPayload.json @@ -27,36 +27,6 @@ "address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", "amount": "32000000000" } - ], - "deposit_requests": [ - { - "pubkey": "0x94e2d4cf94fb757578c496885af2075c26e2483eeffa6e894ac791f7c1945b0fbf9a6f7860736db93e03d511c4b08516", - "withdrawal_credentials": "0x010000000000000000000000a2a06043d17ac951519956f43432e6811a0a4c5e", - "amount": "4853404529811048049", - "signature": "0x85cc5356a9646f0ffd512b7d2e7d3242c81303a415e61b490d28635896aef1f2db03ae8a1439908d03cc131515ef83f003dd7b36ce480c43f4495ffd339b2b9d1e5461309a02ce193202f27d216a4f0e13f7b47295f3e1a44c8f0e8ae8e1e5a8", - "index": "4843489626215975984" - }, - { - "pubkey": "0xa5041469fc5f6a944fda64e7ab422c1479ab9d0de12a2f3ac7292dfe368408cbc6d2b0ff519b521427da731e7378806e", - "withdrawal_credentials": "0x010000000000000000000000fdc8e14312fb98663ed87639047022e291c761d2", - "amount": "4889759173463000754", - "signature": "0xa19b99131e621d31846245039e99d6540418acc08844a3996544cca2d9965f8a24cc49cf695bd78959a784e1b5646b480b88aec749a62ea934ed3001af50bb8babfb15bb9df1f3d57abd738f65de02b77398c82302f500218675cd96ee3b2357", - "index": "4893064144191336306" - } - ], - "withdrawal_requests": [ - { - "source_address": "0x240bd643529257f0285e4590ab814b7c9dcd5ff6", - "validator_pubkey": "0x802775e14fda679e4594ca8ccda68a706957fe82c10e66d258eafd21fe5b2877c226092004f82874fb4022d73b74eea6", - "amount": "4878191786651244561" - } - ], - "consolidation_requests": [ - { - "source_address": "0x240bd643529257f0285e4590ab814b7c9dcd5ff6", - "source_pubkey": "0x802775e14fda679e4594ca8ccda68a706957fe82c10e66d258eafd21fe5b2877c226092004f82874fb4022d73b74eea6", - "target_pubkey": "0x802775e14fda679e4594ca8ccda68a706957fe82c10e66d258eafd21fe5b2877c226092004f82874fb4022d73b74eea6" - } ] }, "blobs_bundle": { diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBid.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBid.java index 2b1cab3dd2e..b0959338a1d 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBid.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBid.java @@ -19,6 +19,7 @@ import tech.pegasys.teku.infrastructure.ssz.SszContainer; import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; public interface BuilderBid extends SszContainer { @@ -27,6 +28,8 @@ public interface BuilderBid extends SszContainer { Optional> getOptionalBlobKzgCommitments(); + Optional getOptionalExecutionRequests(); + UInt256 getValue(); BLSPublicKey getPublicKey(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBidBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBidBuilder.java index 2b68923909c..16652e504f6 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBidBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/BuilderBidBuilder.java @@ -17,6 +17,7 @@ import tech.pegasys.teku.bls.BLSPublicKey; import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; public interface BuilderBidBuilder { @@ -25,6 +26,8 @@ public interface BuilderBidBuilder { BuilderBidBuilder blobKzgCommitments(SszList blobKzgCommitments); + BuilderBidBuilder executionRequests(ExecutionRequests executionRequests); + BuilderBidBuilder value(UInt256 value); BuilderBidBuilder publicKey(BLSPublicKey publicKey); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/ExecutionPayloadAndBlobsBundleSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/ExecutionPayloadAndBlobsBundleSchema.java index 92f6d8e7b0f..7f20e4b998b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/ExecutionPayloadAndBlobsBundleSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/ExecutionPayloadAndBlobsBundleSchema.java @@ -23,9 +23,6 @@ public class ExecutionPayloadAndBlobsBundleSchema extends ContainerSchema2 implements BuilderPayloadSchema { - // TODO Update as part of Builder API Electra updates - // (https://github.com/Consensys/teku/issues/8624) - public ExecutionPayloadAndBlobsBundleSchema( final ExecutionPayloadSchema executionPayloadSchema, final BlobsBundleSchema blobsBundleSchema) { diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBellatrix.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBellatrix.java index 19708164ad9..ca6eaabda44 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBellatrix.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBellatrix.java @@ -22,6 +22,7 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; import tech.pegasys.teku.spec.datastructures.builder.BuilderBid; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; @@ -51,6 +52,11 @@ public Optional> getOptionalBlobKzgCommitments() { return Optional.empty(); } + @Override + public Optional getOptionalExecutionRequests() { + return Optional.empty(); + } + @Override public UInt256 getValue() { return getField1().get(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBuilderBellatrix.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBuilderBellatrix.java index 0ebbbcd70aa..c875389adf0 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBuilderBellatrix.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/bellatrix/BuilderBidBuilderBellatrix.java @@ -22,6 +22,7 @@ import tech.pegasys.teku.spec.datastructures.builder.BuilderBid; import tech.pegasys.teku.spec.datastructures.builder.BuilderBidBuilder; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; @@ -49,6 +50,11 @@ public BuilderBidBuilder blobKzgCommitments(final SszList blob return this; } + @Override + public BuilderBidBuilder executionRequests(final ExecutionRequests executionRequests) { + return this; + } + @Override public BuilderBidBuilder value(final UInt256 value) { this.value = value; diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/deneb/BuilderBidDenebImpl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/deneb/BuilderBidDenebImpl.java index 24cbc9540f3..dd0467da195 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/deneb/BuilderBidDenebImpl.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/deneb/BuilderBidDenebImpl.java @@ -13,6 +13,7 @@ package tech.pegasys.teku.spec.datastructures.builder.versions.deneb; +import java.util.Optional; import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.bls.BLSPublicKey; import tech.pegasys.teku.infrastructure.ssz.SszList; @@ -20,6 +21,7 @@ import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt256; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; @@ -50,6 +52,11 @@ public ExecutionPayloadHeader getHeader() { return getField0(); } + @Override + public Optional getOptionalExecutionRequests() { + return Optional.empty(); + } + @Override public SszList getBlobKzgCommitments() { return getField1(); 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 new file mode 100644 index 00000000000..6f52613f3ce --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidBuilderElectra.java @@ -0,0 +1,58 @@ +/* + * 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.spec.datastructures.builder.versions.electra; + +import static com.google.common.base.Preconditions.checkNotNull; + +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt256; +import tech.pegasys.teku.spec.datastructures.builder.BuilderBid; +import tech.pegasys.teku.spec.datastructures.builder.BuilderBidBuilder; +import tech.pegasys.teku.spec.datastructures.builder.versions.deneb.BuilderBidBuilderDeneb; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; +import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; + +public class BuilderBidBuilderElectra extends BuilderBidBuilderDeneb { + + private BuilderBidSchemaElectra schema; + + protected ExecutionRequests executionRequests; + + public BuilderBidBuilderElectra schema(final BuilderBidSchemaElectra schema) { + this.schema = schema; + return this; + } + + @Override + public BuilderBidBuilder executionRequests(final ExecutionRequests executionRequests) { + this.executionRequests = executionRequests; + return this; + } + + @Override + public BuilderBid build() { + return new BuilderBidElectraImpl( + schema, + header, + blobKzgCommitments, + executionRequests, + SszUInt256.of(value), + new SszPublicKey(publicKey)); + } + + @Override + protected void validate() { + super.validate(); + checkNotNull(executionRequests, "executionRequests must be specified"); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectra.java new file mode 100644 index 00000000000..a4ca8f3087e --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectra.java @@ -0,0 +1,28 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.spec.datastructures.builder.versions.electra; + +import java.util.Optional; +import tech.pegasys.teku.spec.datastructures.builder.versions.deneb.BuilderBidDeneb; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; + +public interface BuilderBidElectra extends BuilderBidDeneb { + + ExecutionRequests getExecutionRequests(); + + @Override + default Optional getOptionalExecutionRequests() { + return Optional.of(getExecutionRequests()); + } +} 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 new file mode 100644 index 00000000000..9a5d2541d5a --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidElectraImpl.java @@ -0,0 +1,75 @@ +/* + * 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.spec.datastructures.builder.versions.electra; + +import org.apache.tuweni.units.bigints.UInt256; +import tech.pegasys.teku.bls.BLSPublicKey; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.infrastructure.ssz.containers.Container5; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt256; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; +import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; + +public class BuilderBidElectraImpl + extends Container5< + BuilderBidElectraImpl, + ExecutionPayloadHeader, + SszList, + ExecutionRequests, + SszUInt256, + SszPublicKey> + implements BuilderBidElectra { + + BuilderBidElectraImpl(final BuilderBidSchemaElectra schema, final TreeNode backingNode) { + super(schema, backingNode); + } + + public BuilderBidElectraImpl( + final BuilderBidSchemaElectra schema, + final ExecutionPayloadHeader header, + final SszList blobKzgCommitments, + final ExecutionRequests executionRequests, + final SszUInt256 value, + final SszPublicKey publicKey) { + super(schema, header, blobKzgCommitments, executionRequests, value, publicKey); + } + + @Override + public ExecutionPayloadHeader getHeader() { + return getField0(); + } + + @Override + public SszList getBlobKzgCommitments() { + return getField1(); + } + + @Override + public ExecutionRequests getExecutionRequests() { + return getField2(); + } + + @Override + public UInt256 getValue() { + return getField3().get(); + } + + @Override + public BLSPublicKey getPublicKey() { + return getField4().getBLSPublicKey(); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidSchemaElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidSchemaElectra.java new file mode 100644 index 00000000000..9e5d3252f45 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/builder/versions/electra/BuilderBidSchemaElectra.java @@ -0,0 +1,71 @@ +/* + * 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.spec.datastructures.builder.versions.electra; + +import java.util.function.Consumer; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema5; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt256; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.schema.SszSchema; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobKzgCommitmentsSchema; +import tech.pegasys.teku.spec.datastructures.builder.BuilderBid; +import tech.pegasys.teku.spec.datastructures.builder.BuilderBidBuilder; +import tech.pegasys.teku.spec.datastructures.builder.BuilderBidSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsSchema; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; +import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; +import tech.pegasys.teku.spec.datastructures.type.SszPublicKeySchema; + +public class BuilderBidSchemaElectra + extends ContainerSchema5< + BuilderBidElectraImpl, + ExecutionPayloadHeader, + SszList, + ExecutionRequests, + SszUInt256, + SszPublicKey> + implements BuilderBidSchema { + + public BuilderBidSchemaElectra( + final String containerName, + final ExecutionPayloadHeaderSchema executionPayloadHeaderSchema, + final BlobKzgCommitmentsSchema blobKzgCommitmentsSchema, + final ExecutionRequestsSchema executionRequestsSchema) { + super( + containerName, + namedSchema( + "header", SszSchema.as(ExecutionPayloadHeader.class, executionPayloadHeaderSchema)), + namedSchema("blob_kzg_commitments", blobKzgCommitmentsSchema), + namedSchema("execution_requests", executionRequestsSchema), + namedSchema("value", SszPrimitiveSchemas.UINT256_SCHEMA), + namedSchema("pubkey", SszPublicKeySchema.INSTANCE)); + } + + @Override + public BuilderBidElectraImpl createFromBackingNode(final TreeNode node) { + return new BuilderBidElectraImpl(this, node); + } + + @Override + public BuilderBid createBuilderBid(final Consumer builderConsumer) { + final BuilderBidBuilderElectra builder = new BuilderBidBuilderElectra().schema(this); + builderConsumer.accept(builder); + return builder.build(); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionPayloadResult.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionPayloadResult.java index 35c85e1ac72..edab3ab3196 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionPayloadResult.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionPayloadResult.java @@ -70,16 +70,17 @@ public Optional>> getBlobsBundleFutureFromLocal getPayloadResponse -> getPayloadResponse.thenApply(GetPayloadResponse::getBlobsBundle)); } - public Optional> getBuilderBidOrFallbackDataFuture() { - return builderBidOrFallbackDataFuture; - } - - public Optional>> getExecutionRequestsFromLocalFlow() { + public Optional>> + getExecutionRequestsFutureFromLocalFlow() { return getPayloadResponseFuture.map( getPayloadResponse -> getPayloadResponse.thenApply(GetPayloadResponse::getExecutionRequests)); } + public Optional> getBuilderBidOrFallbackDataFuture() { + return builderBidOrFallbackDataFuture; + } + /** * @return the value from the local payload, the builder bid or the local fallback payload */ diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/FallbackData.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/FallbackData.java index bd7aee7e959..085dec5d35a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/FallbackData.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/FallbackData.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.Optional; import org.apache.tuweni.units.bigints.UInt256; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; public class FallbackData { @@ -40,6 +41,10 @@ public UInt256 getExecutionPayloadValue() { return getPayloadResponse.getExecutionPayloadValue(); } + public Optional getExecutionRequests() { + return getPayloadResponse.getExecutionRequests(); + } + public FallbackReason getReason() { return reason; } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java index e6f9cdca094..036dcb26cb0 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java @@ -37,7 +37,7 @@ import tech.pegasys.teku.spec.datastructures.builder.BuilderPayloadSchema; import tech.pegasys.teku.spec.datastructures.builder.ExecutionPayloadAndBlobsBundleSchema; import tech.pegasys.teku.spec.datastructures.builder.SignedBuilderBidSchema; -import tech.pegasys.teku.spec.datastructures.builder.versions.deneb.BuilderBidSchemaDeneb; +import tech.pegasys.teku.spec.datastructures.builder.versions.electra.BuilderBidSchemaElectra; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequest; @@ -146,8 +146,11 @@ public SchemaDefinitionsElectra(final SchemaRegistry schemaRegistry) { this.signedBlindedBeaconBlockSchema = new SignedBeaconBlockSchema(blindedBeaconBlockSchema, "SignedBlindedBlockElectra"); this.builderBidSchemaElectra = - new BuilderBidSchemaDeneb( - "BuilderBidElectra", getExecutionPayloadHeaderSchema(), getBlobKzgCommitmentsSchema()); + new BuilderBidSchemaElectra( + "BuilderBidElectra", + getExecutionPayloadHeaderSchema(), + getBlobKzgCommitmentsSchema(), + executionRequestsSchema); this.signedBuilderBidSchemaElectra = new SignedBuilderBidSchema("SignedBuilderBidElectra", builderBidSchemaElectra); 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