|
23 | 23 | import static org.mockito.Mockito.mock;
|
24 | 24 | import static tech.pegasys.teku.spec.SpecMilestone.CAPELLA;
|
25 | 25 | import static tech.pegasys.teku.spec.SpecMilestone.DENEB;
|
| 26 | +import static tech.pegasys.teku.spec.SpecMilestone.ELECTRA; |
26 | 27 |
|
27 | 28 | import com.fasterxml.jackson.annotation.JsonProperty;
|
28 | 29 | import com.fasterxml.jackson.core.JsonFactory;
|
|
43 | 44 | import okhttp3.mockwebserver.RecordedRequest;
|
44 | 45 | import org.apache.tuweni.bytes.Bytes;
|
45 | 46 | import org.apache.tuweni.bytes.Bytes32;
|
| 47 | +import org.assertj.core.api.InstanceOfAssertFactories; |
46 | 48 | import org.junit.jupiter.api.AfterEach;
|
47 | 49 | import org.junit.jupiter.api.BeforeEach;
|
48 | 50 | import org.junit.jupiter.api.TestTemplate;
|
49 | 51 | import tech.pegasys.teku.ethereum.events.ExecutionClientEventsChannel;
|
50 | 52 | import tech.pegasys.teku.ethereum.executionclient.schema.ClientVersionV1;
|
51 | 53 | import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV3;
|
| 54 | +import tech.pegasys.teku.ethereum.executionclient.schema.ExecutionPayloadV4; |
52 | 55 | import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceStateV1;
|
53 | 56 | import tech.pegasys.teku.ethereum.executionclient.schema.ForkChoiceUpdatedResult;
|
54 | 57 | import tech.pegasys.teku.ethereum.executionclient.schema.PayloadAttributesV1;
|
|
69 | 72 | import tech.pegasys.teku.spec.logic.versions.deneb.types.VersionedHash;
|
70 | 73 | import tech.pegasys.teku.spec.util.DataStructureUtil;
|
71 | 74 |
|
72 |
| -@TestSpecContext(milestone = {CAPELLA, DENEB}) |
| 75 | +@TestSpecContext(milestone = {CAPELLA, DENEB, ELECTRA}) |
73 | 76 | public class Web3JExecutionEngineClientTest {
|
74 | 77 |
|
75 | 78 | private static final Duration DEFAULT_TIMEOUT = Duration.ofMinutes(1);
|
@@ -298,6 +301,66 @@ public void newPayloadV3_shouldBuildRequestAndResponseSuccessfully() {
|
298 | 301 | .isEqualTo(parentBeaconBlockRoot.toHexString());
|
299 | 302 | }
|
300 | 303 |
|
| 304 | + @TestTemplate |
| 305 | + @SuppressWarnings("unchecked") |
| 306 | + public void newPayloadV4_shouldBuildRequestAndResponseSuccessfully() { |
| 307 | + assumeThat(specMilestone).isGreaterThanOrEqualTo(ELECTRA); |
| 308 | + final Bytes32 latestValidHash = dataStructureUtil.randomBytes32(); |
| 309 | + final PayloadStatus payloadStatusResponse = |
| 310 | + PayloadStatus.valid(Optional.of(latestValidHash), Optional.empty()); |
| 311 | + |
| 312 | + final String bodyResponse = |
| 313 | + "{\"jsonrpc\": \"2.0\", \"id\": 0, \"result\":" |
| 314 | + + "{ \"status\": \"VALID\", \"latestValidHash\": \"" |
| 315 | + + latestValidHash |
| 316 | + + "\", \"validationError\": null}}"; |
| 317 | + |
| 318 | + mockSuccessfulResponse(bodyResponse); |
| 319 | + |
| 320 | + final ExecutionPayload executionPayload = dataStructureUtil.randomExecutionPayload(); |
| 321 | + final ExecutionPayloadV4 executionPayloadV4 = |
| 322 | + ExecutionPayloadV4.fromInternalExecutionPayload(executionPayload); |
| 323 | + |
| 324 | + final List<VersionedHash> blobVersionedHashes = dataStructureUtil.randomVersionedHashes(3); |
| 325 | + final Bytes32 parentBeaconBlockRoot = dataStructureUtil.randomBytes32(); |
| 326 | + |
| 327 | + final SafeFuture<Response<PayloadStatusV1>> futureResponse = |
| 328 | + eeClient.newPayloadV4(executionPayloadV4, blobVersionedHashes, parentBeaconBlockRoot); |
| 329 | + |
| 330 | + assertThat(futureResponse) |
| 331 | + .succeedsWithin(1, TimeUnit.SECONDS) |
| 332 | + .matches( |
| 333 | + response -> |
| 334 | + response.getPayload().asInternalExecutionPayload().equals(payloadStatusResponse)); |
| 335 | + |
| 336 | + final Map<String, Object> requestData = takeRequest(); |
| 337 | + verifyJsonRpcMethodCall(requestData, "engine_newPayloadV4"); |
| 338 | + |
| 339 | + final Map<String, Object> executionPayloadV4Parameter = |
| 340 | + (Map<String, Object>) ((List<Object>) requestData.get("params")).get(0); |
| 341 | + // 19 fields in ExecutionPayloadV4 |
| 342 | + assertThat(executionPayloadV4Parameter).hasSize(19); |
| 343 | + // sanity check |
| 344 | + assertThat(executionPayloadV4Parameter.get("parentHash")) |
| 345 | + .isEqualTo(executionPayloadV4.parentHash.toHexString()); |
| 346 | + |
| 347 | + assertThat(executionPayloadV4Parameter.get("depositReceipts")) |
| 348 | + .asInstanceOf(InstanceOfAssertFactories.LIST) |
| 349 | + .hasSameSizeAs(executionPayloadV4.depositReceipts); |
| 350 | + assertThat(executionPayloadV4Parameter.get("exits")) |
| 351 | + .asInstanceOf(InstanceOfAssertFactories.LIST) |
| 352 | + .hasSameSizeAs(executionPayloadV4.exits); |
| 353 | + assertThat(((List<Object>) requestData.get("params")).get(1)) |
| 354 | + .asInstanceOf(LIST) |
| 355 | + .containsExactlyElementsOf( |
| 356 | + blobVersionedHashes.stream() |
| 357 | + .map(VersionedHash::toHexString) |
| 358 | + .collect(Collectors.toList())); |
| 359 | + assertThat(((List<Object>) requestData.get("params")).get(2)) |
| 360 | + .asString() |
| 361 | + .isEqualTo(parentBeaconBlockRoot.toHexString()); |
| 362 | + } |
| 363 | + |
301 | 364 | private void mockSuccessfulResponse(final String responseBody) {
|
302 | 365 | mockWebServer.enqueue(
|
303 | 366 | new MockResponse()
|
|
0 commit comments