3378 ws engine (#3493)

* implements execution engine APIs over websockets

Signed-off-by: Justin Florentine <justin+github@florentine.us>
pull/3502/head
Justin Florentine 3 years ago committed by GitHub
parent 889fda9207
commit 174193b884
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 9
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  3. 3
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java
  4. 7
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java
  5. 10
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  6. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java
  7. 45
      besu/src/main/java/org/hyperledger/besu/Runner.java
  8. 47
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  9. 60
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  10. 51
      besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java
  11. 2
      besu/src/test/java/org/hyperledger/besu/RunnerTest.java
  12. 8
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  13. 1
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  14. 1
      besu/src/test/resources/everything_config.toml
  15. 9
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java

@ -13,7 +13,7 @@
- Add PostMergeContext, and stop syncing after the swith to PoS [#3453](https://github.com/hyperledger/besu/pull/3453)
- Add header validation rules needed to validate The Merge blocks [#3454](https://github.com/hyperledger/besu/pull/3454)
- Add core components: controller builder, protocol scheduler, coordinator, block creator and processor. [#3461](https://github.com/hyperledger/besu/pull/3461)
- Execution specific RPC endpoint [#2914](https://github.com/hyperledger/besu/issues/2914), [#3350](https://github.com/hyperledger/besu/pull/3350)
- Execution specific RPC endpoint [#2914](https://github.com/hyperledger/besu/issues/2914), [#3350](https://github.com/hyperledger/besu/pull/3350), [#3378](https://github.com/hyperledger/besu/issues/3378)
- QBFT consensus algorithm is production ready
### Bug Fixes

@ -343,6 +343,15 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
}
}
@Override
public Optional<Integer> getEngineJsonRpcWebSocketPort() {
if (isWebSocketsRpcEnabled()) {
return Optional.of(Integer.valueOf(portsProperties.getProperty("engine-ws-rpc")));
} else {
return Optional.empty();
}
}
@Override
public String getHostName() {
return LOCALHOST;

@ -220,6 +220,9 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
params.add("--rpc-ws-authentication-jwt-algorithm");
params.add(node.webSocketConfiguration().getAuthenticationAlgorithm().toString());
}
// TODO: properly handle engine rpc, set port to 0 to make tests pass
params.add("--engine-rpc-ws-port");
params.add("0");
}
if (node.isMetricsEnabled()) {

@ -39,6 +39,7 @@ public class BesuNodeConfiguration {
private final JsonRpcConfiguration jsonRpcConfiguration;
private final Optional<JsonRpcConfiguration> engineRpcConfiguration;
private final WebSocketConfiguration webSocketConfiguration;
private final Optional<WebSocketConfiguration> engineWebSocketConfiguration;
private final MetricsConfiguration metricsConfiguration;
private final Optional<PermissioningConfiguration> permissioningConfiguration;
private final Optional<String> keyFilePath;
@ -71,6 +72,7 @@ public class BesuNodeConfiguration {
final JsonRpcConfiguration jsonRpcConfiguration,
final Optional<JsonRpcConfiguration> engineRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final Optional<WebSocketConfiguration> engineWebSocketConfiguration,
final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyFilePath,
@ -100,6 +102,7 @@ public class BesuNodeConfiguration {
this.jsonRpcConfiguration = jsonRpcConfiguration;
this.engineRpcConfiguration = engineRpcConfiguration;
this.webSocketConfiguration = webSocketConfiguration;
this.engineWebSocketConfiguration = engineWebSocketConfiguration;
this.metricsConfiguration = metricsConfiguration;
this.permissioningConfiguration = permissioningConfiguration;
this.keyFilePath = keyFilePath;
@ -147,6 +150,10 @@ public class BesuNodeConfiguration {
return webSocketConfiguration;
}
public Optional<WebSocketConfiguration> getEngineWebSocketConfiguration() {
return engineWebSocketConfiguration;
}
public MetricsConfiguration getMetricsConfiguration() {
return metricsConfiguration;
}

@ -59,6 +59,8 @@ public class BesuNodeConfigurationBuilder {
private JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault();
private JsonRpcConfiguration engineRpcConfiguration = JsonRpcConfiguration.createEngineDefault();
private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault();
private WebSocketConfiguration engineWebSocketConfiguration =
WebSocketConfiguration.createDefault();
private MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder().build();
private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty();
private String keyFilePath = null;
@ -89,6 +91,7 @@ public class BesuNodeConfigurationBuilder {
// intermittent failures due to the fact that we're running over a real network
networkingConfiguration.setInitiateConnectionsFrequency(5);
engineRpcConfiguration.setPort(JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT);
engineWebSocketConfiguration.setPort(WebSocketConfiguration.DEFAULT_WEBSOCKET_ENGINE_PORT);
}
public BesuNodeConfigurationBuilder name(final String name) {
@ -134,6 +137,12 @@ public class BesuNodeConfigurationBuilder {
return this;
}
public BesuNodeConfigurationBuilder engineWebSocketConfiguration(
final WebSocketConfiguration engineConfig) {
this.engineWebSocketConfiguration = engineConfig;
return this;
}
public BesuNodeConfigurationBuilder jsonRpcEnabled() {
this.jsonRpcConfiguration.setEnabled(true);
this.jsonRpcConfiguration.setPort(0);
@ -470,6 +479,7 @@ public class BesuNodeConfigurationBuilder {
jsonRpcConfiguration,
Optional.of(engineRpcConfiguration),
webSocketConfiguration,
Optional.of(engineWebSocketConfiguration),
metricsConfiguration,
permissioningConfiguration,
Optional.ofNullable(keyFilePath),

@ -36,6 +36,8 @@ public interface NodeConfiguration {
Optional<Integer> getEngineJsonRpcPort();
Optional<Integer> getEngineJsonRpcWebSocketPort();
String getHostName();
boolean isJsonRpcEnabled();

@ -65,7 +65,8 @@ public class Runner implements AutoCloseable {
private final Optional<JsonRpcHttpService> engineJsonRpc;
private final Optional<MetricsService> metrics;
private final Optional<Path> pidPath;
private final Optional<WebSocketService> websocketRpc;
private final Optional<WebSocketService> webSocketRpc;
private final Optional<WebSocketService> engineWebSocketRpc;
private final TransactionPoolEvictionService transactionPoolEvictionService;
private final BesuController besuController;
@ -81,7 +82,8 @@ public class Runner implements AutoCloseable {
final Optional<JsonRpcHttpService> jsonRpc,
final Optional<JsonRpcHttpService> engineJsonRpc,
final Optional<GraphQLHttpService> graphQLHttp,
final Optional<WebSocketService> websocketRpc,
final Optional<WebSocketService> webSocketRpc,
final Optional<WebSocketService> engineWebSocketRpc,
final Optional<StratumServer> stratumServer,
final Optional<MetricsService> metrics,
final Optional<EthStatsService> ethStatsService,
@ -97,7 +99,8 @@ public class Runner implements AutoCloseable {
this.pidPath = pidPath;
this.jsonRpc = jsonRpc;
this.engineJsonRpc = engineJsonRpc;
this.websocketRpc = websocketRpc;
this.webSocketRpc = webSocketRpc;
this.engineWebSocketRpc = engineWebSocketRpc;
this.metrics = metrics;
this.ethStatsService = ethStatsService;
this.besuController = besuController;
@ -117,7 +120,9 @@ public class Runner implements AutoCloseable {
jsonRpc.ifPresent(service -> waitForServiceToStart("jsonRpc", service.start()));
engineJsonRpc.ifPresent(service -> waitForServiceToStart("engineJsonRpc", service.start()));
graphQLHttp.ifPresent(service -> waitForServiceToStart("graphQLHttp", service.start()));
websocketRpc.ifPresent(service -> waitForServiceToStart("websocketRpc", service.start()));
webSocketRpc.ifPresent(service -> waitForServiceToStart("websocketRpc", service.start()));
engineWebSocketRpc.ifPresent(
service -> waitForServiceToStart("engineWebsocketRpc", service.start()));
stratumServer.ifPresent(server -> waitForServiceToStart("stratum", server.start()));
autoTransactionLogBloomCachingService.ifPresent(AutoTransactionLogBloomCachingService::start);
ethStatsService.ifPresent(EthStatsService::start);
@ -148,7 +153,9 @@ public class Runner implements AutoCloseable {
jsonRpc.ifPresent(service -> waitForServiceToStop("jsonRpc", service.stop()));
engineJsonRpc.ifPresent(service -> waitForServiceToStop("engineJsonRpc", service.stop()));
graphQLHttp.ifPresent(service -> waitForServiceToStop("graphQLHttp", service.stop()));
websocketRpc.ifPresent(service -> waitForServiceToStop("websocketRpc", service.stop()));
webSocketRpc.ifPresent(service -> waitForServiceToStop("websocketRpc", service.stop()));
engineWebSocketRpc.ifPresent(
service -> waitForServiceToStop("engineWebsocketRpc", service.stop()));
metrics.ifPresent(service -> waitForServiceToStop("metrics", service.stop()));
ethStatsService.ifPresent(EthStatsService::stop);
besuController.getMiningCoordinator().stop();
@ -244,17 +251,21 @@ public class Runner implements AutoCloseable {
});
}
if (getJsonRpcPort().isPresent()) {
properties.setProperty("json-rpc", String.valueOf(getJsonRpcPort().get()));
Optional<Integer> port = getJsonRpcPort();
if (port.isPresent()) {
properties.setProperty("json-rpc", String.valueOf(port.get()));
}
if (getGraphQLHttpPort().isPresent()) {
properties.setProperty("graphql-http", String.valueOf(getGraphQLHttpPort().get()));
port = getGraphQLHttpPort();
if (port.isPresent()) {
properties.setProperty("graphql-http", String.valueOf(port.get()));
}
if (getWebsocketPort().isPresent()) {
properties.setProperty("ws-rpc", String.valueOf(getWebsocketPort().get()));
port = getWebSocketPort();
if (port.isPresent()) {
properties.setProperty("ws-rpc", String.valueOf(port.get()));
}
if (getMetricsPort().isPresent()) {
properties.setProperty("metrics", String.valueOf(getMetricsPort().get()));
port = getMetricsPort();
if (port.isPresent()) {
properties.setProperty("metrics", String.valueOf(port.get()));
}
// create besu.ports file
createBesuFile(
@ -317,8 +328,12 @@ public class Runner implements AutoCloseable {
return graphQLHttp.map(service -> service.socketAddress().getPort());
}
public Optional<Integer> getWebsocketPort() {
return websocketRpc.map(service -> service.socketAddress().getPort());
public Optional<Integer> getWebSocketPort() {
return webSocketRpc.map(service -> service.socketAddress().getPort());
}
public Optional<Integer> getEngineWebsocketPort() {
return engineWebSocketRpc.map(service -> service.socketAddress().getPort());
}
public Optional<Integer> getMetricsPort() {

@ -163,6 +163,7 @@ public class RunnerBuilder {
private Optional<JsonRpcConfiguration> engineJsonRpcConfiguration = Optional.empty();
private GraphQLConfiguration graphQLConfiguration;
private WebSocketConfiguration webSocketConfiguration;
private Optional<WebSocketConfiguration> engineWebSocketConfiguration = Optional.empty();
private ApiConfiguration apiConfiguration;
private Path dataDir;
private Optional<Path> pidPath = Optional.empty();
@ -306,6 +307,12 @@ public class RunnerBuilder {
return this;
}
public RunnerBuilder engineWebSocketConfiguration(
final WebSocketConfiguration engineWebSocketConfig) {
this.engineWebSocketConfiguration = Optional.of(engineWebSocketConfig);
return this;
}
public RunnerBuilder apiConfiguration(final ApiConfiguration apiConfiguration) {
this.apiConfiguration = apiConfiguration;
return this;
@ -674,6 +681,7 @@ public class RunnerBuilder {
}
Optional<WebSocketService> webSocketService = Optional.empty();
Optional<WebSocketService> engineWebSocketService = Optional.empty();
if (webSocketConfiguration.isEnabled()) {
final Map<String, JsonRpcMethod> webSocketsJsonRpcMethods =
jsonRpcMethods(
@ -726,6 +734,44 @@ public class RunnerBuilder {
blockchainQueries));
createPrivateTransactionObserver(subscriptionManager, privacyParameters);
if (engineWebSocketConfiguration.isPresent()) {
final Map<String, JsonRpcMethod> engineMethods =
jsonRpcMethods(
protocolSchedule,
context,
besuController,
peerNetwork,
blockchainQueries,
synchronizer,
transactionPool,
miningCoordinator,
metricsSystem,
supportedCapabilities,
engineWebSocketConfiguration.get().getRpcApis(),
filterManager,
accountLocalConfigPermissioningController,
nodeLocalConfigPermissioningController,
privacyParameters,
jsonRpcConfiguration,
engineWebSocketConfiguration.get(),
metricsConfiguration,
natService,
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl);
engineWebSocketService =
Optional.of(
createWebsocketService(
vertx,
engineWebSocketConfiguration.get(),
subscriptionManager,
engineMethods,
privacyParameters,
protocolSchedule,
blockchainQueries));
}
}
Optional<MetricsService> metricsService = createMetricsService(vertx, metricsConfiguration);
@ -757,6 +803,7 @@ public class RunnerBuilder {
engineJsonRpcHttpService,
graphQLHttpService,
webSocketService,
engineWebSocketService,
stratumServer,
metricsService,
ethStatsService,

@ -28,6 +28,7 @@ import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEF
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS;
import static org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration.DEFAULT_WEBSOCKET_ENGINE_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration.DEFAULT_WEBSOCKET_PORT;
import static org.hyperledger.besu.ethereum.permissioning.GoQuorumPermissioningConfiguration.QIP714_DEFAULT_BLOCK;
import static org.hyperledger.besu.metrics.BesuMetricCategory.DEFAULT_METRIC_CATEGORIES;
@ -698,6 +699,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
arity = "1")
private final Integer rpcWsPort = DEFAULT_WEBSOCKET_PORT;
@Option(
names = {"--engine-rpc-ws-port"},
paramLabel = MANDATORY_PORT_FORMAT_HELP,
description =
"Port for Execution Engine JSON-RPC WebSocket service to listen on (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer engineRpcWsPort = DEFAULT_WEBSOCKET_ENGINE_PORT;
@Option(
names = {"--rpc-ws-max-frame-size"},
description =
@ -1193,6 +1202,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private JsonRpcConfiguration engineJsonRpcConfiguration;
private GraphQLConfiguration graphQLConfiguration;
private WebSocketConfiguration webSocketConfiguration;
private WebSocketConfiguration engineWebSocketConfiguration;
private ApiConfiguration apiConfiguration;
private MetricsConfiguration metricsConfiguration;
private Optional<PermissioningConfiguration> permissioningConfiguration;
@ -1496,6 +1506,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
jsonRpcConfiguration,
engineJsonRpcConfiguration,
webSocketConfiguration,
engineWebSocketConfiguration,
apiConfiguration,
metricsConfiguration,
permissioningConfiguration,
@ -1798,11 +1809,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
checkGoQuorumCompatibilityConfig(ethNetworkConfig);
jsonRpcConfiguration = jsonRpcConfiguration();
engineJsonRpcConfiguration = engineJsonRpcConfiguration();
jsonRpcConfiguration = jsonRpcConfiguration(rpcHttpPort, rpcHttpApis, hostsAllowlist);
engineJsonRpcConfiguration =
createEngineJsonRpcConfiguration(engineRpcHttpPort, engineHostsAllowlist);
p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine);
graphQLConfiguration = graphQLConfiguration();
webSocketConfiguration = webSocketConfiguration();
webSocketConfiguration = webSocketConfiguration(rpcWsPort, rpcWsApis, hostsAllowlist);
engineWebSocketConfiguration =
webSocketConfiguration(
engineRpcWsPort, Arrays.asList("ENGINE", "ETH"), engineHostsAllowlist);
apiConfiguration = apiConfiguration();
// hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist
if (!hostsWhitelist.isEmpty()) {
@ -1963,25 +1978,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return graphQLConfiguration;
}
private JsonRpcConfiguration engineJsonRpcConfiguration() {
final JsonRpcConfiguration engineConfig = JsonRpcConfiguration.createDefault();
engineConfig.setEnabled(isRpcHttpEnabled);
engineConfig.setHost(rpcHttpHost);
engineConfig.setPort(engineRpcHttpPort);
engineConfig.setMaxActiveConnections(rpcHttpMaxConnections);
engineConfig.setCorsAllowedDomains(rpcHttpCorsAllowedOrigins);
engineConfig.setRpcApis(Arrays.asList("ENGINE", "ETH"));
engineConfig.setHostsAllowlist(engineHostsAllowlist);
engineConfig.setAuthenticationEnabled(isRpcHttpAuthenticationEnabled);
engineConfig.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile());
engineConfig.setAuthenticationPublicKeyFile(rpcHttpAuthenticationPublicKeyFile);
engineConfig.setAuthenticationAlgorithm(rpcHttpAuthenticationAlgorithm);
engineConfig.setTlsConfiguration(rpcHttpTlsConfiguration());
engineConfig.setHttpTimeoutSec(unstableRPCOptions.getHttpTimeoutSec());
private JsonRpcConfiguration createEngineJsonRpcConfiguration(
final Integer listenPort, final List<String> allowCallsFrom) {
JsonRpcConfiguration engineConfig =
jsonRpcConfiguration(listenPort, Arrays.asList("ENGINE", "ETH"), allowCallsFrom);
return engineConfig;
}
private JsonRpcConfiguration jsonRpcConfiguration() {
private JsonRpcConfiguration jsonRpcConfiguration(
final Integer listenPort, final List<String> apiGroups, final List<String> allowCallsFrom) {
checkRpcTlsClientAuthOptionsDependencies();
checkRpcTlsOptionsDependencies();
checkRpcHttpOptionsDependencies();
@ -2006,13 +2011,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault();
jsonRpcConfiguration.setEnabled(isRpcHttpEnabled);
jsonRpcConfiguration.setHost(rpcHttpHost);
jsonRpcConfiguration.setPort(rpcHttpPort);
jsonRpcConfiguration.setPort(listenPort);
jsonRpcConfiguration.setMaxActiveConnections(rpcHttpMaxConnections);
jsonRpcConfiguration.setCorsAllowedDomains(rpcHttpCorsAllowedOrigins);
jsonRpcConfiguration.setRpcApis(rpcHttpApis.stream().distinct().collect(Collectors.toList()));
jsonRpcConfiguration.setRpcApis(apiGroups.stream().distinct().collect(Collectors.toList()));
jsonRpcConfiguration.setNoAuthRpcApis(
rpcHttpApiMethodsNoAuth.stream().distinct().collect(Collectors.toList()));
jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist);
jsonRpcConfiguration.setHostsAllowlist(allowCallsFrom);
jsonRpcConfiguration.setAuthenticationEnabled(isRpcHttpAuthenticationEnabled);
jsonRpcConfiguration.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile());
jsonRpcConfiguration.setAuthenticationPublicKeyFile(rpcHttpAuthenticationPublicKeyFile);
@ -2158,7 +2163,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return isRpcHttpEnabled && isRpcHttpTlsEnabled;
}
private WebSocketConfiguration webSocketConfiguration() {
private WebSocketConfiguration webSocketConfiguration(
final Integer listenPort, final List<String> apiGroups, final List<String> allowCallsFrom) {
CommandLineUtils.checkOptionDependencies(
logger,
@ -2199,15 +2205,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault();
webSocketConfiguration.setEnabled(isRpcWsEnabled);
webSocketConfiguration.setHost(rpcWsHost);
webSocketConfiguration.setPort(rpcWsPort);
webSocketConfiguration.setPort(listenPort);
webSocketConfiguration.setMaxFrameSize(rpcWsMaxFrameSize);
webSocketConfiguration.setMaxActiveConnections(rpcWsMaxConnections);
webSocketConfiguration.setRpcApis(rpcWsApis);
webSocketConfiguration.setRpcApis(apiGroups);
webSocketConfiguration.setRpcApisNoAuth(
rpcWsApiMethodsNoAuth.stream().distinct().collect(Collectors.toList()));
webSocketConfiguration.setAuthenticationEnabled(isRpcWsAuthenticationEnabled);
webSocketConfiguration.setAuthenticationCredentialsFile(rpcWsAuthenticationCredentialsFile());
webSocketConfiguration.setHostsAllowlist(hostsAllowlist);
webSocketConfiguration.setHostsAllowlist(allowCallsFrom);
webSocketConfiguration.setAuthenticationPublicKeyFile(rpcWsAuthenticationPublicKeyFile);
webSocketConfiguration.setAuthenticationAlgorithm(rpcWebsocketsAuthenticationAlgorithm);
webSocketConfiguration.setTimeoutSec(unstableRPCOptions.getWsTimeoutSec());
@ -2578,6 +2584,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final JsonRpcConfiguration jsonRpcConfiguration,
final JsonRpcConfiguration engineJsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final WebSocketConfiguration engineWebSocketConfiguration,
final ApiConfiguration apiConfiguration,
final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration,
@ -2613,6 +2620,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.jsonRpcConfiguration(jsonRpcConfiguration)
.engineJsonRpcConfiguration(engineJsonRpcConfiguration)
.webSocketConfiguration(webSocketConfiguration)
.engineWebSocketConfiguration(engineWebSocketConfiguration)
.apiConfiguration(apiConfiguration)
.pidPath(pidPath)
.dataDir(dataDir())

@ -253,10 +253,52 @@ public final class RunnerBuilderTest {
assertThat(runner.getEngineJsonRpcPort()).isPresent();
}
@Test
public void whenEngineApiAddedWebSocketReadyOnDefaultPort() {
WebSocketConfiguration wsRpc = WebSocketConfiguration.createDefault();
wsRpc.setEnabled(true);
WebSocketConfiguration engineWsRpc = WebSocketConfiguration.createEngineDefault();
engineWsRpc.setEnabled(true);
EthNetworkConfig mockMainnet = mock(EthNetworkConfig.class);
when(mockMainnet.getNetworkId()).thenReturn(BigInteger.ONE);
MergeConfigOptions.setMergeEnabled(true);
when(besuController.getMiningCoordinator()).thenReturn(mock(MergeMiningCoordinator.class));
final Runner runner =
new RunnerBuilder()
.discovery(true)
.p2pListenInterface("0.0.0.0")
.p2pListenPort(30303)
.p2pAdvertisedHost("127.0.0.1")
.p2pEnabled(true)
.natMethod(NatMethod.NONE)
.besuController(besuController)
.ethNetworkConfig(mockMainnet)
.metricsSystem(mock(ObservableMetricsSystem.class))
.permissioningService(mock(PermissioningServiceImpl.class))
.jsonRpcConfiguration(JsonRpcConfiguration.createDefault())
.webSocketConfiguration(wsRpc)
.engineWebSocketConfiguration(engineWsRpc)
.graphQLConfiguration(mock(GraphQLConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx())
.dataDir(dataDir.getRoot().toPath())
.storageProvider(mock(KeyValueStorageProvider.class))
.forkIdSupplier(() -> Collections.singletonList(Bytes.EMPTY))
.rpcEndpointService(new RpcEndpointServiceImpl())
.besuPluginContext(mock(BesuPluginContextImpl.class))
.build();
assertThat(runner.getWebSocketPort()).isPresent();
assertThat(runner.getEngineWebsocketPort()).isPresent();
}
@Test
public void noEngineApiNoServiceForMethods() {
JsonRpcConfiguration defaultPlusEng = JsonRpcConfiguration.createDefault();
defaultPlusEng.setEnabled(true);
JsonRpcConfiguration defaultRpcConfig = JsonRpcConfiguration.createDefault();
defaultRpcConfig.setEnabled(true);
WebSocketConfiguration defaultWebSockConfig = WebSocketConfiguration.createDefault();
defaultWebSockConfig.setEnabled(true);
EthNetworkConfig mockMainnet = mock(EthNetworkConfig.class);
when(mockMainnet.getNetworkId()).thenReturn(BigInteger.ONE);
MergeConfigOptions.setMergeEnabled(true);
@ -274,9 +316,9 @@ public final class RunnerBuilderTest {
.ethNetworkConfig(mockMainnet)
.metricsSystem(mock(ObservableMetricsSystem.class))
.permissioningService(mock(PermissioningServiceImpl.class))
.jsonRpcConfiguration(defaultPlusEng)
.jsonRpcConfiguration(defaultRpcConfig)
.graphQLConfiguration(mock(GraphQLConfiguration.class))
.webSocketConfiguration(mock(WebSocketConfiguration.class))
.webSocketConfiguration(defaultWebSockConfig)
.metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx())
.dataDir(dataDir.getRoot().toPath())
@ -288,5 +330,6 @@ public final class RunnerBuilderTest {
assertThat(runner.getJsonRpcPort()).isPresent();
assertThat(runner.getEngineJsonRpcPort()).isEmpty();
assertThat(runner.getEngineWebsocketPort()).isEmpty();
}
}

@ -354,7 +354,7 @@ public final class RunnerTest {
final Promise<String> promise = Promise.promise();
final HttpClient httpClient = vertx.createHttpClient();
httpClient.webSocket(
runnerBehind.getWebsocketPort().get(),
runnerBehind.getWebSocketPort().get(),
WebSocketConfiguration.DEFAULT_WEBSOCKET_HOST,
"/",
ws -> {

@ -46,6 +46,7 @@ import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
@ -2568,7 +2569,9 @@ public class BesuCommandTest extends CommandTestAbstract {
String.valueOf(port),
"--rpc-http-tls-cipher-suite",
cipherSuites);
verify(mockLogger)
verify(
mockLogger,
times(2)) // this is verified for both the full suite of apis, and the engine group.
.warn(
"{} has been ignored because {} was not defined on the command line.",
"--rpc-http-tls-cipher-suite",
@ -3031,8 +3034,9 @@ public class BesuCommandTest extends CommandTestAbstract {
@Test
public void rpcWsApiPropertyMustBeUsed() {
parseCommand("--rpc-ws-enabled", "--rpc-ws-api", "ETH, NET");
TestBesuCommand command = parseCommand("--rpc-ws-enabled", "--rpc-ws-api", "ETH, NET");
assertThat(command).isNotNull();
verify(mockRunnerBuilder).webSocketConfiguration(wsRpcConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();

@ -265,6 +265,7 @@ public abstract class CommandTestAbstract {
when(mockRunnerBuilder.natMethodFallbackEnabled(anyBoolean())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.jsonRpcConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.engineJsonRpcConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.engineWebSocketConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.graphQLConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.webSocketConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.apiConfiguration(any())).thenReturn(mockRunnerBuilder);

@ -99,6 +99,7 @@ rpc-ws-api=["DEBUG","ETH"]
rpc-ws-apis=["DEBUG","ETH"]
rpc-ws-host="9.10.11.12"
rpc-ws-port=9101
engine-rpc-ws-port=9102
rpc-ws-max-active-connections=101
rpc-ws-max-frame-size=65535
rpc-ws-authentication-enabled=false

@ -31,6 +31,7 @@ import com.google.common.base.MoreObjects;
public class WebSocketConfiguration {
public static final String DEFAULT_WEBSOCKET_HOST = "127.0.0.1";
public static final int DEFAULT_WEBSOCKET_PORT = 8546;
public static final int DEFAULT_WEBSOCKET_ENGINE_PORT = 8551;
public static final int DEFAULT_WEBSOCKET_MAX_FRAME_SIZE = 1024 * 1024;
public static final int DEFAULT_MAX_ACTIVE_CONNECTIONS = 80;
@ -60,6 +61,14 @@ public class WebSocketConfiguration {
return config;
}
public static WebSocketConfiguration createEngineDefault() {
final WebSocketConfiguration config = createDefault();
config.setPort(DEFAULT_WEBSOCKET_ENGINE_PORT);
config.setRpcApis(Arrays.asList("ENGINE", "ETH"));
config.setHostsAllowlist(Arrays.asList("localhost", "127.0.0.1"));
return config;
}
private WebSocketConfiguration() {}
public boolean isEnabled() {

Loading…
Cancel
Save