mirror of https://github.com/hyperledger/besu
Implement engine_exchangeCapabilities (#4997)
https://github.com/ethereum/execution-apis/pull/364 Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Signed-off-by: Simon Dudley <simon.dudley@consensys.net>pull/5001/head
parent
0503407c22
commit
897c7a79e0
@ -0,0 +1,77 @@ |
||||
/* |
||||
* 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.methods.engine; |
||||
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod.ENGINE_EXCHANGE_CAPABILITIES; |
||||
import static org.hyperledger.besu.util.Slf4jLambdaHelper.traceLambda; |
||||
|
||||
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.methods.ExecutionEngineJsonRpcMethod; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
import java.util.stream.Stream; |
||||
|
||||
import io.vertx.core.Vertx; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class EngineExchangeCapabilities extends ExecutionEngineJsonRpcMethod { |
||||
private static final Logger LOG = LoggerFactory.getLogger(EngineExchangeCapabilities.class); |
||||
|
||||
public EngineExchangeCapabilities( |
||||
final Vertx vertx, |
||||
final ProtocolContext protocolContext, |
||||
final EngineCallListener engineCallListener) { |
||||
super(vertx, protocolContext, engineCallListener); |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return ENGINE_EXCHANGE_CAPABILITIES.getMethodName(); |
||||
} |
||||
|
||||
@Override |
||||
public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) { |
||||
engineCallListener.executionEngineCalled(); |
||||
|
||||
final List<String> remoteCapabilities = |
||||
Arrays.stream(requestContext.getRequest().getParams()) |
||||
.map(String::valueOf) |
||||
.collect(Collectors.toList()); |
||||
final Object reqId = requestContext.getRequest().getId(); |
||||
|
||||
traceLambda(LOG, "received remote capabilities: {}", () -> remoteCapabilities); |
||||
|
||||
final List<String> localCapabilities = |
||||
Stream.of(RpcMethod.values()) |
||||
.filter(e -> e.getMethodName().startsWith("engine_")) |
||||
.filter(e -> !e.equals(ENGINE_EXCHANGE_CAPABILITIES)) |
||||
.map(RpcMethod::getMethodName) |
||||
.collect(Collectors.toList()); |
||||
|
||||
return respondWith(reqId, localCapabilities); |
||||
} |
||||
|
||||
private JsonRpcResponse respondWith( |
||||
final Object requestId, final List<String> localCapabilities) { |
||||
return new JsonRpcSuccessResponse(requestId, localCapabilities); |
||||
} |
||||
} |
@ -0,0 +1,93 @@ |
||||
/* |
||||
* 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.methods.engine; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod.ENGINE_EXCHANGE_CAPABILITIES; |
||||
import static org.mockito.Mockito.times; |
||||
import static org.mockito.Mockito.verify; |
||||
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext; |
||||
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.response.JsonRpcResponse; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponseType; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import io.vertx.core.Vertx; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mock; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
|
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class EngineExchangeCapabilitiesTest { |
||||
private EngineExchangeCapabilities method; |
||||
private static final Vertx vertx = Vertx.vertx(); |
||||
|
||||
@Mock private ProtocolContext protocolContext; |
||||
|
||||
@Mock private EngineCallListener engineCallListener; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
this.method = new EngineExchangeCapabilities(vertx, protocolContext, engineCallListener); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnExpectedMethodName() { |
||||
assertThat(method.getName()).isEqualTo("engine_exchangeCapabilities"); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnAllSupportedEngineApiRpcNames() { |
||||
var response = resp(List.of("engine_newPayloadV1", "engine_newPayloadV2", "nonsense")); |
||||
|
||||
var result = fromSuccessResp(response); |
||||
assertThat(result).allMatch(name -> name.startsWith("engine_")); |
||||
verify(engineCallListener, times(1)).executionEngineCalled(); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldNotReturnSelf() { |
||||
var response = resp(Collections.emptyList()); |
||||
|
||||
var result = fromSuccessResp(response); |
||||
assertThat(result).allMatch(name -> !ENGINE_EXCHANGE_CAPABILITIES.getMethodName().equals(name)); |
||||
verify(engineCallListener, times(1)).executionEngineCalled(); |
||||
} |
||||
|
||||
private JsonRpcResponse resp(final List<String> params) { |
||||
return method.response( |
||||
new JsonRpcRequestContext( |
||||
new JsonRpcRequest( |
||||
"2.0", ENGINE_EXCHANGE_CAPABILITIES.getMethodName(), params.toArray()))); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private List<String> fromSuccessResp(final JsonRpcResponse resp) { |
||||
assertThat(resp.getType()).isEqualTo(JsonRpcResponseType.SUCCESS); |
||||
return Optional.of(resp) |
||||
.map(JsonRpcSuccessResponse.class::cast) |
||||
.map(JsonRpcSuccessResponse::getResult) |
||||
.map(List.class::cast) |
||||
.get(); |
||||
} |
||||
} |
Loading…
Reference in new issue