Skip to content

Commit

Permalink
Added executionRequestsHash to EngineNewPayloadV4 (#8666)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucassaldanha authored Oct 2, 2024
1 parent 3b87509 commit a929217
Show file tree
Hide file tree
Showing 23 changed files with 186 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
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/8620
// TODO Re-enable electra as part of https://github.com/Consensys/teku/issues/8624
@TestSpecContext(
milestone = {BELLATRIX, CAPELLA, DENEB},
network = Eth2Network.MAINNET)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
import tech.pegasys.teku.ethereum.events.ExecutionClientEventsChannel;
import tech.pegasys.teku.ethereum.executionclient.schema.ClientVersionV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
import tech.pegasys.teku.ethereum.executionclient.schema.PayloadAttributesV1;
Expand Down Expand Up @@ -317,14 +316,16 @@ public void newPayloadV4_shouldBuildRequestAndResponseSuccessfully() {
mockSuccessfulResponse(bodyResponse);

final ExecutionPayload executionPayload = dataStructureUtil.randomExecutionPayload();
final ExecutionPayloadV4 executionPayloadV4 =
ExecutionPayloadV4.fromInternalExecutionPayload(executionPayload);
final ExecutionPayloadV3 executionPayloadV3 =
ExecutionPayloadV3.fromInternalExecutionPayload(executionPayload);

final List<VersionedHash> blobVersionedHashes = dataStructureUtil.randomVersionedHashes(3);
final Bytes32 parentBeaconBlockRoot = dataStructureUtil.randomBytes32();
final Bytes32 executionRequestHash = dataStructureUtil.randomBytes32();

final SafeFuture<Response<PayloadStatusV1>> futureResponse =
eeClient.newPayloadV4(executionPayloadV4, blobVersionedHashes, parentBeaconBlockRoot);
eeClient.newPayloadV4(
executionPayloadV3, blobVersionedHashes, parentBeaconBlockRoot, executionRequestHash);

assertThat(futureResponse)
.succeedsWithin(1, TimeUnit.SECONDS)
Expand All @@ -335,13 +336,13 @@ public void newPayloadV4_shouldBuildRequestAndResponseSuccessfully() {
final Map<String, Object> requestData = takeRequest();
verifyJsonRpcMethodCall(requestData, "engine_newPayloadV4");

final Map<String, Object> executionPayloadV4Parameter =
final Map<String, Object> executionPayloadV3Parameter =
(Map<String, Object>) ((List<Object>) requestData.get("params")).get(0);
// 17 fields in ExecutionPayloadV4
assertThat(executionPayloadV4Parameter).hasSize(17);
assertThat(executionPayloadV3Parameter).hasSize(17);
// sanity check
assertThat(executionPayloadV4Parameter.get("parentHash"))
.isEqualTo(executionPayloadV4.parentHash.toHexString());
assertThat(executionPayloadV3Parameter.get("parentHash"))
.isEqualTo(executionPayloadV3.parentHash.toHexString());

assertThat(((List<Object>) requestData.get("params")).get(1))
.asInstanceOf(LIST)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV2;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
import tech.pegasys.teku.ethereum.executionclient.schema.GetPayloadV2Response;
Expand Down Expand Up @@ -61,9 +60,10 @@ SafeFuture<Response<PayloadStatusV1>> newPayloadV3(
Bytes32 parentBeaconBlockRoot);

SafeFuture<Response<PayloadStatusV1>> newPayloadV4(
ExecutionPayloadV4 executionPayload,
ExecutionPayloadV3 executionPayload,
List<VersionedHash> blobVersionedHashes,
Bytes32 parentBeaconBlockRoot);
Bytes32 parentBeaconBlockRoot,
Bytes32 executionRequestHash);

SafeFuture<Response<ForkChoiceUpdatedResult>> forkChoiceUpdatedV1(
ForkChoiceStateV1 forkChoiceState, Optional<PayloadAttributesV1> payloadAttributes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV2;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
import tech.pegasys.teku.ethereum.executionclient.schema.GetPayloadV2Response;
Expand Down Expand Up @@ -109,11 +108,17 @@ public SafeFuture<Response<PayloadStatusV1>> newPayloadV3(

@Override
public SafeFuture<Response<PayloadStatusV1>> newPayloadV4(
final ExecutionPayloadV4 executionPayload,
final ExecutionPayloadV3 executionPayload,
final List<VersionedHash> blobVersionedHashes,
final Bytes32 parentBeaconBlockRoot) {
final Bytes32 parentBeaconBlockRoot,
final Bytes32 executionRequestHash) {
return taskQueue.queueTask(
() -> delegate.newPayloadV4(executionPayload, blobVersionedHashes, parentBeaconBlockRoot));
() ->
delegate.newPayloadV4(
executionPayload,
blobVersionedHashes,
parentBeaconBlockRoot,
executionRequestHash));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
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.ExecutionPayloadV4;
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;
Expand Down Expand Up @@ -51,18 +51,21 @@ public SafeFuture<PayloadStatus> execute(final JsonRpcRequestParams params) {
final List<VersionedHash> blobVersionedHashes =
params.getRequiredListParameter(1, VersionedHash.class);
final Bytes32 parentBeaconBlockRoot = params.getRequiredParameter(2, Bytes32.class);
final Bytes32 executionRequestHash = params.getRequiredParameter(3, Bytes32.class);

LOG.trace(
"Calling {}(executionPayload={}, blobVersionedHashes={}, parentBeaconBlockRoot={})",
"Calling {}(executionPayload={}, blobVersionedHashes={}, parentBeaconBlockRoot={}, executionRequestHash={})",
getVersionedName(),
executionPayload,
blobVersionedHashes,
parentBeaconBlockRoot);
parentBeaconBlockRoot,
executionRequestHash);

final ExecutionPayloadV4 executionPayloadV4 =
ExecutionPayloadV4.fromInternalExecutionPayload(executionPayload);
final ExecutionPayloadV3 executionPayloadV3 =
ExecutionPayloadV3.fromInternalExecutionPayload(executionPayload);
return executionEngineClient
.newPayloadV4(executionPayloadV4, blobVersionedHashes, parentBeaconBlockRoot)
.newPayloadV4(
executionPayloadV3, blobVersionedHashes, parentBeaconBlockRoot, executionRequestHash)
.thenApply(ResponseUnwrapper::unwrapExecutionClientResponseOrThrow)
.thenApply(PayloadStatusV1::asInternalExecutionPayload)
.thenPeek(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV2;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
import tech.pegasys.teku.ethereum.executionclient.schema.GetPayloadV2Response;
Expand Down Expand Up @@ -139,11 +138,14 @@ public SafeFuture<Response<PayloadStatusV1>> newPayloadV3(

@Override
public SafeFuture<Response<PayloadStatusV1>> newPayloadV4(
final ExecutionPayloadV4 executionPayload,
final ExecutionPayloadV3 executionPayload,
final List<VersionedHash> blobVersionedHashes,
final Bytes32 parentBeaconBlockRoot) {
final Bytes32 parentBeaconBlockRoot,
final Bytes32 executionRequestHash) {
return countRequest(
() -> delegate.newPayloadV4(executionPayload, blobVersionedHashes, parentBeaconBlockRoot),
() ->
delegate.newPayloadV4(
executionPayload, blobVersionedHashes, parentBeaconBlockRoot, executionRequestHash),
NEW_PAYLOAD_V4_METHOD);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV2;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
import tech.pegasys.teku.ethereum.executionclient.schema.GetPayloadV2Response;
Expand Down Expand Up @@ -176,16 +175,20 @@ public SafeFuture<Response<PayloadStatusV1>> newPayloadV3(

@Override
public SafeFuture<Response<PayloadStatusV1>> newPayloadV4(
final ExecutionPayloadV4 executionPayload,
final ExecutionPayloadV3 executionPayload,
final List<VersionedHash> blobVersionedHashes,
final Bytes32 parentBeaconBlockRoot) {
final Bytes32 parentBeaconBlockRoot,
final Bytes32 executionRequestHash) {
final List<String> expectedBlobVersionedHashes =
blobVersionedHashes.stream().map(VersionedHash::toHexString).toList();
final Request<?, PayloadStatusV1Web3jResponse> web3jRequest =
new Request<>(
"engine_newPayloadV4",
list(
executionPayload, expectedBlobVersionedHashes, parentBeaconBlockRoot.toHexString()),
executionPayload,
expectedBlobVersionedHashes,
parentBeaconBlockRoot.toHexString(),
executionRequestHash.toHexString()),
web3JClient.getWeb3jService(),
PayloadStatusV1Web3jResponse.class);
return web3JClient.doRequest(web3jRequest, EL_ENGINE_BLOCK_EXECUTION_TIMEOUT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.ethereum.executionclient.ExecutionEngineClient;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4;
import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
import tech.pegasys.teku.ethereum.executionclient.schema.PayloadStatusV1;
import tech.pegasys.teku.ethereum.executionclient.schema.Response;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
Expand Down Expand Up @@ -71,21 +71,66 @@ public void executionPayloadParamIsRequired() {
verifyNoInteractions(executionEngineClient);
}

@Test
public void blobVersionedHashesParamIsRequired() {
final JsonRpcRequestParams params =
new JsonRpcRequestParams.Builder().add(dataStructureUtil.randomExecutionPayload()).build();

assertThatThrownBy(() -> jsonRpcMethod.execute(params))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Missing required parameter at index 1");

verifyNoInteractions(executionEngineClient);
}

@Test
public void parentBeaconBlockRootParamIsRequired() {
final JsonRpcRequestParams params =
new JsonRpcRequestParams.Builder()
.add(dataStructureUtil.randomExecutionPayload())
.add(dataStructureUtil.randomVersionedHashes(3))
.build();

assertThatThrownBy(() -> jsonRpcMethod.execute(params))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Missing required parameter at index 2");

verifyNoInteractions(executionEngineClient);
}

@Test
public void executionRequestHashParamIsRequired() {
final JsonRpcRequestParams params =
new JsonRpcRequestParams.Builder()
.add(dataStructureUtil.randomExecutionPayload())
.add(dataStructureUtil.randomVersionedHashes(3))
.add(dataStructureUtil.randomBytes32())
.build();

assertThatThrownBy(() -> jsonRpcMethod.execute(params))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Missing required parameter at index 3");

verifyNoInteractions(executionEngineClient);
}

@Test
public void shouldReturnFailedExecutionWhenEngineClientRequestFails() {
final ExecutionPayload executionPayload = dataStructureUtil.randomExecutionPayload();
final List<VersionedHash> blobVersionedHashes = dataStructureUtil.randomVersionedHashes(3);
final Bytes32 parentBeaconBlockRoot = dataStructureUtil.randomBytes32();
final Bytes32 executionRequestHash = dataStructureUtil.randomBytes32();
final String errorResponseFromClient = "error!";

when(executionEngineClient.newPayloadV4(any(), any(), any()))
when(executionEngineClient.newPayloadV4(any(), any(), any(), any()))
.thenReturn(dummyFailedResponse(errorResponseFromClient));

final JsonRpcRequestParams params =
new JsonRpcRequestParams.Builder()
.add(executionPayload)
.add(blobVersionedHashes)
.add(parentBeaconBlockRoot)
.add(executionRequestHash)
.build();

assertThat(jsonRpcMethod.execute(params))
Expand All @@ -94,32 +139,41 @@ public void shouldReturnFailedExecutionWhenEngineClientRequestFails() {
}

@Test
public void shouldCallNewPayloadV4WithExecutionPayloadV4AndBlobVersionedHashes() {
public void shouldCallNewPayloadV4WithExecutionPayloadV3AndCorrectParameters() {
final ExecutionPayload executionPayload = dataStructureUtil.randomExecutionPayload();
final List<VersionedHash> blobVersionedHashes = dataStructureUtil.randomVersionedHashes(4);
final Bytes32 parentBeaconBlockRoot = dataStructureUtil.randomBytes32();
final Bytes32 executionRequestHash = dataStructureUtil.randomBytes32();

final ExecutionPayloadV4 executionPayloadV4 =
ExecutionPayloadV4.fromInternalExecutionPayload(executionPayload);
assertThat(executionPayloadV4).isExactlyInstanceOf(ExecutionPayloadV4.class);
final ExecutionPayloadV3 executionPayloadV3 =
ExecutionPayloadV3.fromInternalExecutionPayload(executionPayload);
assertThat(executionPayloadV3).isExactlyInstanceOf(ExecutionPayloadV3.class);

jsonRpcMethod = new EngineNewPayloadV4(executionEngineClient);

when(executionEngineClient.newPayloadV4(
executionPayloadV4, blobVersionedHashes, parentBeaconBlockRoot))
eq(executionPayloadV3),
eq(blobVersionedHashes),
eq(parentBeaconBlockRoot),
eq(executionRequestHash)))
.thenReturn(dummySuccessfulResponse());

final JsonRpcRequestParams params =
new JsonRpcRequestParams.Builder()
.add(executionPayload)
.add(blobVersionedHashes)
.add(parentBeaconBlockRoot)
.add(executionRequestHash)
.build();

assertThat(jsonRpcMethod.execute(params)).isCompleted();

verify(executionEngineClient)
.newPayloadV4(eq(executionPayloadV4), eq(blobVersionedHashes), eq(parentBeaconBlockRoot));
.newPayloadV4(
eq(executionPayloadV3),
eq(blobVersionedHashes),
eq(parentBeaconBlockRoot),
eq(executionRequestHash));
verifyNoMoreInteractions(executionEngineClient);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ SafeFuture<ForkChoiceUpdatedResult> engineForkChoiceUpdated(
SafeFuture<GetPayloadResponse> engineGetPayload(
ExecutionPayloadContext executionPayloadContext, UInt64 slot);

SafeFuture<PayloadStatus> engineNewPayload(NewPayloadRequest newPayloadRequest);
SafeFuture<PayloadStatus> engineNewPayload(NewPayloadRequest newPayloadRequest, UInt64 slot);

SafeFuture<List<ClientVersion>> engineGetClientVersion(ClientVersion clientVersion);
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,21 @@ public SafeFuture<GetPayloadResponse> engineGetPayload(
}

@Override
public SafeFuture<PayloadStatus> engineNewPayload(final NewPayloadRequest newPayloadRequest) {
public SafeFuture<PayloadStatus> engineNewPayload(
final NewPayloadRequest newPayloadRequest, final UInt64 slot) {
final ExecutionPayload executionPayload = newPayloadRequest.getExecutionPayload();
final JsonRpcRequestParams.Builder paramsBuilder =
new JsonRpcRequestParams.Builder()
.add(executionPayload)
.addOptional(newPayloadRequest.getVersionedHashes())
.addOptional(newPayloadRequest.getParentBeaconBlockRoot());
.addOptional(newPayloadRequest.getParentBeaconBlockRoot())
.addOptional(newPayloadRequest.getExecutionRequestsHash());

return engineMethodsResolver
.getMethod(
EngineApiMethod.ENGINE_NEW_PAYLOAD, executionPayload::getMilestone, PayloadStatus.class)
EngineApiMethod.ENGINE_NEW_PAYLOAD,
() -> spec.atSlot(slot).getMilestone(),
PayloadStatus.class)
.execute(paramsBuilder.build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ private SafeFuture<GetPayloadResponse> engineGetPayload(
}

@Override
public SafeFuture<PayloadStatus> engineNewPayload(final NewPayloadRequest newPayloadRequest) {
public SafeFuture<PayloadStatus> engineNewPayload(
final NewPayloadRequest newPayloadRequest, final UInt64 slot) {
LOG.trace("calling engineNewPayload(newPayloadRequest={})", newPayloadRequest);
return executionClientHandler.engineNewPayload(newPayloadRequest);
return executionClientHandler.engineNewPayload(newPayloadRequest, slot);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void engineNewPayload_shouldCallNewPayloadV1() {
new PayloadStatusV1(
ExecutionPayloadStatus.ACCEPTED, dataStructureUtil.randomBytes32(), null)));
when(executionEngineClient.newPayloadV1(payloadV1)).thenReturn(dummyResponse);
handler.engineNewPayload(newPayloadRequest);
handler.engineNewPayload(newPayloadRequest, UInt64.ZERO);
verify(executionEngineClient).newPayloadV1(payloadV1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ void engineNewPayload_shouldCallNewPayloadV2() {
new PayloadStatusV1(
ExecutionPayloadStatus.ACCEPTED, dataStructureUtil.randomBytes32(), null)));
when(executionEngineClient.newPayloadV2(payloadV2)).thenReturn(dummyResponse);
final SafeFuture<PayloadStatus> future = handler.engineNewPayload(newPayloadRequest);
final SafeFuture<PayloadStatus> future =
handler.engineNewPayload(newPayloadRequest, UInt64.ZERO);
verify(executionEngineClient).newPayloadV2(payloadV2);
assertThat(future).isCompleted();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ void engineNewPayload_shouldCallNewPayloadV3() {
ExecutionPayloadStatus.ACCEPTED, dataStructureUtil.randomBytes32(), null)));
when(executionEngineClient.newPayloadV3(payloadV3, versionedHashes, parentBeaconBlockRoot))
.thenReturn(dummyResponse);
final SafeFuture<PayloadStatus> future = handler.engineNewPayload(newPayloadRequest);
final SafeFuture<PayloadStatus> future =
handler.engineNewPayload(newPayloadRequest, UInt64.ZERO);
verify(executionEngineClient).newPayloadV3(payloadV3, versionedHashes, parentBeaconBlockRoot);
assertThat(future).isCompleted();
}
Expand Down
Loading

0 comments on commit a929217

Please sign in to comment.