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
Simon Dudley 2 years ago committed by GitHub
parent 0503407c22
commit 897c7a79e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java
  2. 77
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeCapabilities.java
  3. 4
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ExecutionEngineJsonRpcMethods.java
  4. 93
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeCapabilitiesTest.java

@ -55,6 +55,7 @@ public enum RpcMethod {
ENGINE_FORKCHOICE_UPDATED_V1("engine_forkchoiceUpdatedV1"),
ENGINE_FORKCHOICE_UPDATED_V2("engine_forkchoiceUpdatedV2"),
ENGINE_EXCHANGE_TRANSITION_CONFIGURATION("engine_exchangeTransitionConfigurationV1"),
ENGINE_EXCHANGE_CAPABILITIES("engine_exchangeCapabilities"),
GOQUORUM_ETH_GET_QUORUM_PAYLOAD("eth_getQuorumPayload"),
GOQUORUM_STORE_RAW("goquorum_storeRaw"),

@ -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);
}
}

@ -18,6 +18,7 @@ import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineExchangeCapabilities;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineExchangeTransitionConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV1;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV2;
@ -112,7 +113,8 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
mergeCoordinator.get(),
engineQosTimer),
new EngineExchangeTransitionConfiguration(
consensusEngineServer, protocolContext, engineQosTimer));
consensusEngineServer, protocolContext, engineQosTimer),
new EngineExchangeCapabilities(consensusEngineServer, protocolContext, engineQosTimer));
} else {
return mapOf(
new EngineExchangeTransitionConfiguration(

@ -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…
Cancel
Save