diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index d70b1cc1997..cb93cd92ba2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -32,9 +32,11 @@ import org.hyperledger.besu.ethereum.BlockProcessingResult; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExecutionPayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineNewPayloadRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; @@ -64,6 +66,7 @@ import java.security.InvalidParameterException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -99,26 +102,25 @@ public AbstractEngineNewPayload( @Override public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) { engineCallListener.executionEngineCalled(); - - final EnginePayloadParameter blockParam = - requestContext.getRequiredParameter(0, EnginePayloadParameter.class); - - final Optional> maybeVersionedHashParam = - requestContext.getOptionalList(1, String.class); - final Object reqId = requestContext.getRequest().getId(); - Optional maybeParentBeaconBlockRootParam = - requestContext.getOptionalParameter(2, String.class); - final Optional maybeParentBeaconBlockRoot = - maybeParentBeaconBlockRootParam.map(Bytes32::fromHexString); + EngineNewPayloadRequestParameter requestParameters; + try { + requestParameters = getEngineNewPayloadRequestParams(requestContext); + } catch (InvalidJsonRpcParameters exception) { + return new JsonRpcErrorResponse( + requestContext.getRequest().getId(), + new JsonRpcError(INVALID_PARAMS, exception.getMessage())); + } final ValidationResult parameterValidationResult = - validateParameters(blockParam, maybeVersionedHashParam, maybeParentBeaconBlockRootParam); + validateParameters(requestParameters); + if (!parameterValidationResult.isValid()) { return new JsonRpcErrorResponse(reqId, parameterValidationResult); } + EngineExecutionPayloadParameter blockParam = requestParameters.getExecutionPayload(); final ValidationResult forkValidationResult = validateForkSupported(blockParam.getTimestamp()); if (!forkValidationResult.isValid()) { @@ -127,7 +129,8 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) final Optional> maybeVersionedHashes; try { - maybeVersionedHashes = extractVersionedHashes(maybeVersionedHashParam); + maybeVersionedHashes = + extractVersionedHashes(requestParameters.getExpectedBlobVersionedHashes()); } catch (RuntimeException ex) { return respondWithInvalid(reqId, blockParam, null, INVALID, "Invalid versionedHash"); } @@ -213,7 +216,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) blockParam.getExcessBlobGas() == null ? null : BlobGas.fromHexString(blockParam.getExcessBlobGas()), - maybeParentBeaconBlockRoot.orElse(null), + requestParameters.getParentBeaconBlockRoot().map(Bytes32::fromHexString).orElse(null), maybeDeposits.map(BodyValidation::depositsRoot).orElse(null), headerFunctions); @@ -318,7 +321,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) JsonRpcResponse respondWith( final Object requestId, - final EnginePayloadParameter param, + final EngineExecutionPayloadParameter param, final Hash latestValidHash, final EngineStatus status) { if (INVALID.equals(status) || INVALID_BLOCK_HASH.equals(status)) { @@ -343,7 +346,7 @@ JsonRpcResponse respondWith( JsonRpcResponse respondWithInvalid( final Object requestId, - final EnginePayloadParameter param, + final EngineExecutionPayloadParameter param, final Hash latestValidHash, final EngineStatus invalidStatus, final String validationError) { @@ -382,9 +385,7 @@ protected EngineStatus getInvalidBlockHashStatus() { } protected ValidationResult validateParameters( - final EnginePayloadParameter parameter, - final Optional> maybeVersionedHashParam, - final Optional maybeBeaconBlockRootParam) { + final EngineNewPayloadRequestParameter params) { return ValidationResult.valid(); } @@ -475,6 +476,27 @@ private Optional> extractVersionedHashes( .collect(Collectors.toList())); } + /** + * Retrieves the new payload request parameters from the given JSON-RPC request context. + * + * @param requestContext the JSON-RPC request context + * @return a new instance of EngineNewPayloadRequestParameter + */ + public EngineNewPayloadRequestParameter getEngineNewPayloadRequestParams( + final JsonRpcRequestContext requestContext) { + + final EngineExecutionPayloadParameter payload = + requestContext.getRequiredParameter(0, EngineExecutionPayloadParameter.class); + final String[] versionedHashes = requestContext.getRequiredParameter(1, String[].class); + + final String parentBeaconBlockRoot = requestContext.getRequiredParameter(2, String.class); + + return new EngineNewPayloadRequestParameter( + payload, + Optional.of(Arrays.stream(versionedHashes).toList()), + Optional.of(parentBeaconBlockRoot)); + } + private void logImportedBlockInfo(final Block block, final double timeInS) { final StringBuilder message = new StringBuilder(); message.append("Imported #%,d / %d tx"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1.java index d7019543c02..f3731617430 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1.java @@ -20,6 +20,9 @@ import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExecutionPayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineNewPayloadRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; @@ -60,6 +63,13 @@ protected EngineStatus getInvalidBlockHashStatus() { return INVALID_BLOCK_HASH; } + @Override + public EngineNewPayloadRequestParameter getEngineNewPayloadRequestParams( + final JsonRpcRequestContext requestContext) { + return new EngineNewPayloadRequestParameter( + requestContext.getRequiredParameter(0, EngineExecutionPayloadParameter.class)); + } + @Override protected ValidationResult validateBlobs( final List transactions, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java index 65133718ada..dc35c6b9f33 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java @@ -18,7 +18,9 @@ import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExecutionPayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineNewPayloadRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; @@ -51,20 +53,25 @@ public String getName() { @Override protected ValidationResult validateParameters( - final EnginePayloadParameter payloadParameter, - final Optional> maybeVersionedHashParam, - final Optional maybeBeaconBlockRootParam) { - if (payloadParameter.getBlobGasUsed() != null) { + final EngineNewPayloadRequestParameter params) { + if (params.getExecutionPayload().getBlobGasUsed() != null) { return ValidationResult.invalid( RpcErrorType.INVALID_PARAMS, "non-null BlobGasUsed pre-cancun"); } - if (payloadParameter.getExcessBlobGas() != null) { + if (params.getExecutionPayload().getExcessBlobGas() != null) { return ValidationResult.invalid( RpcErrorType.INVALID_PARAMS, "non-null ExcessBlobGas pre-cancun"); } return ValidationResult.valid(); } + @Override + public EngineNewPayloadRequestParameter getEngineNewPayloadRequestParams( + final JsonRpcRequestContext requestContext) { + return new EngineNewPayloadRequestParameter( + requestContext.getRequiredParameter(0, EngineExecutionPayloadParameter.class)); + } + @Override protected ValidationResult validateBlobs( final List transactions, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java index f444b4dca58..f6a20770ba8 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3.java @@ -17,14 +17,13 @@ import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineNewPayloadRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; -import java.util.List; import java.util.Optional; import io.vertx.core.Vertx; @@ -52,20 +51,12 @@ public String getName() { @Override protected ValidationResult validateParameters( - final EnginePayloadParameter payloadParameter, - final Optional> maybeVersionedHashParam, - final Optional maybeBeaconBlockRootParam) { - if (payloadParameter.getBlobGasUsed() == null || payloadParameter.getExcessBlobGas() == null) { + final EngineNewPayloadRequestParameter params) { + if (params.getExecutionPayload().getBlobGasUsed() == null + || params.getExecutionPayload().getExcessBlobGas() == null) { return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Missing blob gas fields"); - } else if (maybeVersionedHashParam == null) { - return ValidationResult.invalid( - RpcErrorType.INVALID_PARAMS, "Missing versioned hashes field"); - } else if (maybeBeaconBlockRootParam.isEmpty()) { - return ValidationResult.invalid( - RpcErrorType.INVALID_PARAMS, "Missing parent beacon block root field"); - } else { - return ValidationResult.valid(); } + return ValidationResult.valid(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExecutionPayloadParameter.java similarity index 98% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java rename to ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExecutionPayloadParameter.java index 1834b99a5db..1a00e689360 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExecutionPayloadParameter.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.tuweni.bytes.Bytes32; -public class EnginePayloadParameter { +public class EngineExecutionPayloadParameter { private final Hash blockHash; private final Hash parentHash; private final Address feeRecipient; @@ -68,7 +68,7 @@ public class EnginePayloadParameter { * @param deposits List of deposit parameters. */ @JsonCreator - public EnginePayloadParameter( + public EngineExecutionPayloadParameter( @JsonProperty("blockHash") final Hash blockHash, @JsonProperty("parentHash") final Hash parentHash, @JsonProperty("feeRecipient") final Address feeRecipient, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineNewPayloadRequestParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineNewPayloadRequestParameter.java new file mode 100644 index 00000000000..9b5a648bd80 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineNewPayloadRequestParameter.java @@ -0,0 +1,79 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; + +import java.util.List; +import java.util.Optional; + +/** Represents the parameters for a new payload request in the Ethereum engine. */ +public class EngineNewPayloadRequestParameter { + + private final EngineExecutionPayloadParameter executionPayload; + private final Optional> expectedBlobVersionedHashes; + private final Optional parentBeaconBlockRoot; + + /** + * Constructs a new payload request parameter with only an execution payload. + * + * @param payload the execution payload + */ + public EngineNewPayloadRequestParameter(final EngineExecutionPayloadParameter payload) { + this(payload, Optional.empty(), Optional.empty()); + } + + /** + * Constructs a new payload request parameter with an execution payload, expected blob versioned + * hashes, and a parent beacon block root. + * + * @param executionPayload the execution payload + * @param expectedBlobVersionedHashes the expected blob versioned hashes + * @param parentBeaconBlockRoot the parent beacon block root + */ + public EngineNewPayloadRequestParameter( + final EngineExecutionPayloadParameter executionPayload, + final Optional> expectedBlobVersionedHashes, + final Optional parentBeaconBlockRoot) { + this.executionPayload = executionPayload; + this.expectedBlobVersionedHashes = expectedBlobVersionedHashes; + this.parentBeaconBlockRoot = parentBeaconBlockRoot; + } + + /** + * Returns the execution payload. + * + * @return the execution payload + */ + public EngineExecutionPayloadParameter getExecutionPayload() { + return executionPayload; + } + + /** + * Returns the expected blob versioned hashes. + * + * @return the expected blob versioned hashes + */ + public Optional> getExpectedBlobVersionedHashes() { + return expectedBlobVersionedHashes; + } + + /** + * Returns the parent beacon block root. + * + * @return the parent beacon block root + */ + public Optional getParentBeaconBlockRoot() { + return parentBeaconBlockRoot; + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index a545883a6c8..eee69a36a1e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -40,7 +40,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExecutionPayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; @@ -389,7 +389,7 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { assertValidResponse(mockHeader, resp); } - protected JsonRpcResponse resp(final EnginePayloadParameter payload) { + protected JsonRpcResponse resp(final EngineExecutionPayloadParameter payload) { Object[] params = maybeParentBeaconBlockRoot .map(bytes32 -> new Object[] {payload, null, bytes32.toHexString()}) @@ -398,17 +398,17 @@ protected JsonRpcResponse resp(final EnginePayloadParameter payload) { new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); } - protected EnginePayloadParameter mockEnginePayload( + protected EngineExecutionPayloadParameter mockEnginePayload( final BlockHeader header, final List txs) { return mockEnginePayload(header, txs, null, null); } - protected EnginePayloadParameter mockEnginePayload( + protected EngineExecutionPayloadParameter mockEnginePayload( final BlockHeader header, final List txs, final List withdrawals, final List deposits) { - return new EnginePayloadParameter( + return new EngineExecutionPayloadParameter( header.getHash(), header.getParentHash(), header.getCoinbase(), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadEIP6110Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadEIP6110Test.java index f7ff7894969..0cd927aca27 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadEIP6110Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadEIP6110Test.java @@ -170,7 +170,7 @@ protected BlockHeader createBlockHeader( .baseFeePerGas(Wei.ONE) .timestamp(super.experimentalHardfork.milestone()) .excessBlobGas(BlobGas.ZERO) - .blobGasUsed(100L) + .blobGasUsed(0L) .buildHeader(); BlockHeader mockHeader = @@ -181,10 +181,9 @@ protected BlockHeader createBlockHeader( .timestamp(parentBlockHeader.getTimestamp() + 1) .withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null)) .excessBlobGas(BlobGas.ZERO) - .blobGasUsed(100L) + .blobGasUsed(0L) .depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null)) - .parentBeaconBlockRoot( - maybeParentBeaconBlockRoot.isPresent() ? maybeParentBeaconBlockRoot : null) + .parentBeaconBlockRoot(maybeParentBeaconBlockRoot) .buildHeader(); return mockHeader; } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java index 56cecbfb7db..72d84d3cd5a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java @@ -30,7 +30,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExecutionPayloadParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineNewPayloadRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; @@ -85,7 +86,7 @@ public void before() { public void shouldInvalidVersionedHash_whenShortVersionedHash() { final Bytes shortHash = Bytes.fromHexString("0x" + "69".repeat(31)); - final EnginePayloadParameter payload = mock(EnginePayloadParameter.class); + final EngineExecutionPayloadParameter payload = mock(EngineExecutionPayloadParameter.class); when(payload.getTimestamp()).thenReturn(cancunHardfork.milestone()); when(payload.getExcessBlobGas()).thenReturn("99"); when(payload.getBlobGasUsed()).thenReturn(9l); @@ -113,14 +114,16 @@ public void shouldValidVersionedHash_whenListIsEmpty() { new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), Optional.empty(), Optional.empty()); - final EnginePayloadParameter payload = + final EngineExecutionPayloadParameter payload = mockEnginePayload(mockHeader, Collections.emptyList(), null, null); - ValidationResult res = - method.validateParameters( + EngineNewPayloadRequestParameter params = + new EngineNewPayloadRequestParameter( payload, Optional.of(List.of()), Optional.of("0x0000000000000000000000000000000000000000000000000000000000000000")); + + ValidationResult res = method.validateParameters(params); assertThat(res.isValid()).isTrue(); } @@ -194,4 +197,54 @@ public void shouldValidateExcessBlobGasCorrectly() { assertThat(jsonRpcError.getData()).isEqualTo("Missing blob gas fields"); verify(engineCallListener, times(1)).executionEngineCalled(); } + + @Test + public void shouldReturnInvalidParameterWhenVersionedHashesIsNull() { + EngineExecutionPayloadParameter payload = mock(EngineExecutionPayloadParameter.class); + JsonRpcResponse badParam = + method.response( + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", + RpcMethod.ENGINE_NEW_PAYLOAD_V3.getMethodName(), + new Object[] { + payload, + null, + "0x0000000000000000000000000000000000000000000000000000000000000000" + }))); + JsonRpcError res = fromErrorResp(badParam); + assertThat(res.getCode()).isEqualTo(RpcErrorType.INVALID_PARAMS.getCode()); + assertThat(res.getData()).isEqualTo("Missing required json rpc parameter at index 1"); + } + + @Test + public void shouldReturnInvalidParameterWhenParentBeaconRootIsNull() { + EngineExecutionPayloadParameter payload = mock(EngineExecutionPayloadParameter.class); + JsonRpcResponse badParam = + method.response( + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", + RpcMethod.ENGINE_NEW_PAYLOAD_V3.getMethodName(), + new Object[] {payload, List.of(), null}))); + JsonRpcError res = fromErrorResp(badParam); + assertThat(res.getCode()).isEqualTo(RpcErrorType.INVALID_PARAMS.getCode()); + assertThat(res.getData()).isEqualTo("Missing required json rpc parameter at index 2"); + } + + protected JsonRpcResponse resp( + final EngineExecutionPayloadParameter payload, final List hashes) { + String parentBeaconBlockRoot = maybeParentBeaconBlockRoot.get().toHexString(); + Object[] params = new Object[] {payload, hashes, parentBeaconBlockRoot}; + return method.response( + new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); + } + + @Override + protected JsonRpcResponse resp(final EngineExecutionPayloadParameter payload) { + String parentBeaconBlockRoot = maybeParentBeaconBlockRoot.get().toHexString(); + Object[] params = new Object[] {payload, List.of(), parentBeaconBlockRoot}; + return method.response( + new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); + } }