From a4a9b0d58eeb7e1d6d4d51915c7f89da7a6c49fc Mon Sep 17 00:00:00 2001 From: Mehdi AOUADI Date: Fri, 31 Jan 2025 15:23:30 +0100 Subject: [PATCH] add engine new payload V5 --- .../ExecutionEngineClient.java | 7 ++ .../ThrottlingExecutionEngineClient.java | 17 ++++ .../methods/EngineNewPayloadV5.java | 87 +++++++++++++++++++ .../MetricRecordingExecutionEngineClient.java | 19 ++++ .../web3j/Web3JExecutionEngineClient.java | 25 ++++++ .../ExecutionClientHandlerImpl.java | 3 +- ...toneBasedEngineJsonRpcMethodsResolver.java | 3 +- .../execution/NewPayloadRequest.java | 27 +++++- 8 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/methods/EngineNewPayloadV5.java diff --git a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ExecutionEngineClient.java b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ExecutionEngineClient.java index 521510ee976..50a65c13a18 100644 --- a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ExecutionEngineClient.java +++ b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ExecutionEngineClient.java @@ -68,6 +68,13 @@ SafeFuture> newPayloadV4( Bytes32 parentBeaconBlockRoot, List executionRequests); + SafeFuture> newPayloadV5( + ExecutionPayloadV3 executionPayload, + List blobVersionedHashes, + Bytes32 parentBeaconBlockRoot, + List executionRequests, + List inclusionList); + SafeFuture> forkChoiceUpdatedV1( ForkChoiceStateV1 forkChoiceState, Optional payloadAttributes); diff --git a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ThrottlingExecutionEngineClient.java b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ThrottlingExecutionEngineClient.java index a4f34690cef..817cbd9a6ca 100644 --- a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ThrottlingExecutionEngineClient.java +++ b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/ThrottlingExecutionEngineClient.java @@ -121,6 +121,23 @@ public SafeFuture> newPayloadV4( executionPayload, blobVersionedHashes, parentBeaconBlockRoot, executionRequests)); } + @Override + public SafeFuture> newPayloadV5( + final ExecutionPayloadV3 executionPayload, + final List blobVersionedHashes, + final Bytes32 parentBeaconBlockRoot, + final List executionRequests, + final List inclusionList) { + return taskQueue.queueTask( + () -> + delegate.newPayloadV5( + executionPayload, + blobVersionedHashes, + parentBeaconBlockRoot, + executionRequests, + inclusionList)); + } + @Override public SafeFuture> forkChoiceUpdatedV1( final ForkChoiceStateV1 forkChoiceState, diff --git a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/methods/EngineNewPayloadV5.java b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/methods/EngineNewPayloadV5.java new file mode 100644 index 00000000000..440f866fb02 --- /dev/null +++ b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/methods/EngineNewPayloadV5.java @@ -0,0 +1,87 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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.ethereum.executionclient.methods; + +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.ethereum.executionclient.ExecutionEngineClient; +import tech.pegasys.teku.ethereum.executionclient.response.ResponseUnwrapper; +import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3; +import tech.pegasys.teku.ethereum.executionclient.schema.PayloadStatusV1; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; +import tech.pegasys.teku.spec.executionlayer.PayloadStatus; +import tech.pegasys.teku.spec.logic.versions.deneb.types.VersionedHash; + +public class EngineNewPayloadV5 extends AbstractEngineJsonRpcMethod { + + private static final Logger LOG = LogManager.getLogger(); + + public EngineNewPayloadV5(final ExecutionEngineClient executionEngineClient) { + super(executionEngineClient); + } + + @Override + public String getName() { + return EngineApiMethod.ENGINE_NEW_PAYLOAD.getName(); + } + + @Override + public int getVersion() { + return 5; + } + + @Override + public SafeFuture execute(final JsonRpcRequestParams params) { + final ExecutionPayload executionPayload = + params.getRequiredParameter(0, ExecutionPayload.class); + final List blobVersionedHashes = + params.getRequiredListParameter(1, VersionedHash.class); + final Bytes32 parentBeaconBlockRoot = params.getRequiredParameter(2, Bytes32.class); + final List executionRequests = params.getRequiredListParameter(3, Bytes.class); + final List inclusionList = params.getRequiredListParameter(4, Bytes.class); + + LOG.trace( + "Calling {}(executionPayload={}, blobVersionedHashes={}, parentBeaconBlockRoot={}, executionRequests={}, inclusionList={})", + getVersionedName(), + executionPayload, + blobVersionedHashes, + parentBeaconBlockRoot, + executionRequests, + inclusionList); + + final ExecutionPayloadV3 executionPayloadV3 = + ExecutionPayloadV3.fromInternalExecutionPayload(executionPayload); + return executionEngineClient + .newPayloadV5( + executionPayloadV3, + blobVersionedHashes, + parentBeaconBlockRoot, + executionRequests, + inclusionList) + .thenApply(ResponseUnwrapper::unwrapExecutionClientResponseOrThrow) + .thenApply(PayloadStatusV1::asInternalExecutionPayload) + .thenPeek( + payloadStatus -> + LOG.trace( + "Response {}(executionPayload={}) -> {}", + getVersionedName(), + executionPayload, + payloadStatus)) + .exceptionally(PayloadStatus::failedExecution); + } +} diff --git a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/metrics/MetricRecordingExecutionEngineClient.java b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/metrics/MetricRecordingExecutionEngineClient.java index 775cabaac0a..00285cf6430 100644 --- a/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/metrics/MetricRecordingExecutionEngineClient.java +++ b/ethereum/executionclient/src/main/java/tech/pegasys/teku/ethereum/executionclient/metrics/MetricRecordingExecutionEngineClient.java @@ -66,6 +66,7 @@ public class MetricRecordingExecutionEngineClient extends MetricRecordingAbstrac public static final String GET_PAYLOAD_V4_METHOD = "get_payloadV4"; public static final String NEW_PAYLOAD_V3_METHOD = "new_payloadV3"; public static final String NEW_PAYLOAD_V4_METHOD = "new_payloadV4"; + public static final String NEW_PAYLOAD_V5_METHOD = "new_payloadV5"; public static final String EXCHANGE_CAPABILITIES_METHOD = "exchange_capabilities"; public static final String GET_CLIENT_VERSION_V1_METHOD = "get_client_versionV1"; public static final String GET_BLOBS_V1_METHOD = "get_blobs_versionV1"; @@ -154,6 +155,24 @@ public SafeFuture> newPayloadV4( NEW_PAYLOAD_V4_METHOD); } + @Override + public SafeFuture> newPayloadV5( + final ExecutionPayloadV3 executionPayload, + final List blobVersionedHashes, + final Bytes32 parentBeaconBlockRoot, + final List executionRequests, + final List inclusionList) { + return countRequest( + () -> + delegate.newPayloadV5( + executionPayload, + blobVersionedHashes, + parentBeaconBlockRoot, + executionRequests, + inclusionList), + NEW_PAYLOAD_V5_METHOD); + } + @Override public SafeFuture> forkChoiceUpdatedV1( final ForkChoiceStateV1 forkChoiceState, 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 e45e1c38868..00a6eb423a8 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 @@ -201,6 +201,31 @@ public SafeFuture> newPayloadV4( return web3JClient.doRequest(web3jRequest, EL_ENGINE_BLOCK_EXECUTION_TIMEOUT); } + @Override + public SafeFuture> newPayloadV5( + final ExecutionPayloadV3 executionPayload, + final List blobVersionedHashes, + final Bytes32 parentBeaconBlockRoot, + final List executionRequests, + final List inclusionList) { + final List expectedBlobVersionedHashes = + blobVersionedHashes.stream().map(VersionedHash::toHexString).toList(); + final List executionRequestsHexList = + executionRequests.stream().map(Bytes::toHexString).toList(); + final Request web3jRequest = + new Request<>( + "engine_newPayloadV5", + list( + executionPayload, + expectedBlobVersionedHashes, + parentBeaconBlockRoot.toHexString(), + inclusionList, + executionRequestsHexList), + web3JClient.getWeb3jService(), + PayloadStatusV1Web3jResponse.class); + return web3JClient.doRequest(web3jRequest, EL_ENGINE_BLOCK_EXECUTION_TIMEOUT); + } + @Override public SafeFuture> forkChoiceUpdatedV1( final ForkChoiceStateV1 forkChoiceState, diff --git a/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionClientHandlerImpl.java b/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionClientHandlerImpl.java index 92c15552cfa..5303f6fd814 100644 --- a/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionClientHandlerImpl.java +++ b/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/ExecutionClientHandlerImpl.java @@ -115,7 +115,8 @@ public SafeFuture engineNewPayload( .add(executionPayload) .addOptional(newPayloadRequest.getVersionedHashes()) .addOptional(newPayloadRequest.getParentBeaconBlockRoot()) - .addOptional(newPayloadRequest.getExecutionRequests()); + .addOptional(newPayloadRequest.getExecutionRequests()) + .addOptional(newPayloadRequest.getInclusionList()); return engineMethodsResolver .getMethod( diff --git a/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/MilestoneBasedEngineJsonRpcMethodsResolver.java b/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/MilestoneBasedEngineJsonRpcMethodsResolver.java index e78c74d11c6..6d4f61c6bf1 100644 --- a/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/MilestoneBasedEngineJsonRpcMethodsResolver.java +++ b/ethereum/executionlayer/src/main/java/tech/pegasys/teku/ethereum/executionlayer/MilestoneBasedEngineJsonRpcMethodsResolver.java @@ -40,6 +40,7 @@ import tech.pegasys.teku.ethereum.executionclient.methods.EngineNewPayloadV2; import tech.pegasys.teku.ethereum.executionclient.methods.EngineNewPayloadV3; import tech.pegasys.teku.ethereum.executionclient.methods.EngineNewPayloadV4; +import tech.pegasys.teku.ethereum.executionclient.methods.EngineNewPayloadV5; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.datastructures.util.ForkAndSpecMilestone; @@ -128,7 +129,7 @@ private Map> electraSupportedMethods() { private Map> eip7805SupportedMethods() { final Map> methods = new HashMap<>(); - methods.put(ENGINE_NEW_PAYLOAD, new EngineNewPayloadV4(executionEngineClient)); + methods.put(ENGINE_NEW_PAYLOAD, new EngineNewPayloadV5(executionEngineClient)); methods.put(ENGINE_GET_PAYLOAD, new EngineGetPayloadV4(executionEngineClient, spec)); methods.put(ENGINE_FORK_CHOICE_UPDATED, new EngineForkChoiceUpdatedV3(executionEngineClient)); methods.put(ENGINE_GET_INCLUSION_LIST, new EngineGetInclusionListV1(executionEngineClient)); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/NewPayloadRequest.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/NewPayloadRequest.java index 174e7e686a4..45766046ba7 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/NewPayloadRequest.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/NewPayloadRequest.java @@ -27,12 +27,14 @@ public class NewPayloadRequest { private final Optional> versionedHashes; private final Optional parentBeaconBlockRoot; private final Optional> executionRequests; + private final Optional> inclusionList; public NewPayloadRequest(final ExecutionPayload executionPayload) { this.executionPayload = executionPayload; this.versionedHashes = Optional.empty(); this.parentBeaconBlockRoot = Optional.empty(); this.executionRequests = Optional.empty(); + this.inclusionList = Optional.empty(); } public NewPayloadRequest( @@ -43,6 +45,7 @@ public NewPayloadRequest( this.versionedHashes = Optional.of(versionedHashes); this.parentBeaconBlockRoot = Optional.of(parentBeaconBlockRoot); this.executionRequests = Optional.empty(); + this.inclusionList = Optional.empty(); } public NewPayloadRequest( @@ -54,6 +57,20 @@ public NewPayloadRequest( this.versionedHashes = Optional.of(versionedHashes); this.parentBeaconBlockRoot = Optional.of(parentBeaconBlockRoot); this.executionRequests = Optional.of(executionRequests); + this.inclusionList = Optional.empty(); + } + + public NewPayloadRequest( + final ExecutionPayload executionPayload, + final List versionedHashes, + final Bytes32 parentBeaconBlockRoot, + final List executionRequests, + final List inclusionList) { + this.executionPayload = executionPayload; + this.versionedHashes = Optional.of(versionedHashes); + this.parentBeaconBlockRoot = Optional.of(parentBeaconBlockRoot); + this.executionRequests = Optional.of(executionRequests); + this.inclusionList = Optional.of(inclusionList); } public ExecutionPayload getExecutionPayload() { @@ -72,6 +89,10 @@ public Optional> getExecutionRequests() { return executionRequests; } + public Optional> getInclusionList() { + return inclusionList; + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -84,13 +105,14 @@ public boolean equals(final Object o) { return Objects.equals(executionPayload, that.executionPayload) && Objects.equals(versionedHashes, that.versionedHashes) && Objects.equals(parentBeaconBlockRoot, that.parentBeaconBlockRoot) - && Objects.equals(executionRequests, that.executionRequests); + && Objects.equals(executionRequests, that.executionRequests) + && Objects.equals(inclusionList, that.inclusionList); } @Override public int hashCode() { return Objects.hash( - executionPayload, versionedHashes, parentBeaconBlockRoot, executionRequests); + executionPayload, versionedHashes, parentBeaconBlockRoot, executionRequests, inclusionList); } @Override @@ -100,6 +122,7 @@ public String toString() { .add("versionedHashes", versionedHashes) .add("parentBeaconBlockRoot", parentBeaconBlockRoot) .add("executionRequests", executionRequests) + .add("inclusionList", inclusionList) .toString(); } }