Skip to content

Commit

Permalink
Implement engine_exchangeCapabilities
Browse files Browse the repository at this point in the history
ethereum/execution-apis#364
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
  • Loading branch information
siladu committed Jan 24, 2023
1 parent ab42080 commit 2081078
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down Expand Up @@ -112,7 +113,8 @@ protected Map<String, JsonRpcMethod> create() {
mergeCoordinator.get(),
engineQosTimer),
new EngineExchangeTransitionConfiguration(
consensusEngineServer, protocolContext, engineQosTimer));
consensusEngineServer, protocolContext, engineQosTimer),
new EngineExchangeCapabilities(consensusEngineServer, protocolContext, engineQosTimer));
} else {
return mapOf(
new EngineExchangeTransitionConfiguration(
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit 2081078

Please sign in to comment.