Skip to content

Commit

Permalink
PAN-2485#Add net_services json rpc endpoint (PegaSysEng#1295)
Browse files Browse the repository at this point in the history
Implemented a JSON RPC method "net_services" that takes no input
parameter and returns an object
containing a list of enabled services (jsonrpc, p2p, ws, metrics) with
"host" and "port", as show below;

{
  "id":1,
  "jsonrpc": "2.0",
  "result": {
    "jsonrpc": {"host": "127.0.0.1", "port":3000},
    "p2p":{"host": "127.0.0.1", "port":3000},
    "ws":{"host": "127.0.0.1", "port":3000},
    "metrics":{"host": "127.0.0.1", "port":3000}
  }
}
In case a service is not enabled, that will not be included in the list;

{
  "id":1,
  "jsonrpc": "2.0",
  "result": {}
}

Fixes PAN-2485
  • Loading branch information
usmananwar authored and notlesh committed Apr 24, 2019
1 parent 33c0794 commit 318c41b
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterRepository;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
Expand All @@ -40,6 +41,7 @@
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -88,6 +90,9 @@ public Map<String, JsonRpcMethod> methods() {
final Optional<NodeLocalConfigPermissioningController> nodeWhitelistController =
Optional.of(mock(NodeLocalConfigPermissioningController.class));
final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
final JsonRpcConfiguration jsonRpcConfiguration = mock(JsonRpcConfiguration.class);
final WebSocketConfiguration webSocketConfiguration = mock(WebSocketConfiguration.class);
final MetricsConfiguration metricsConfiguration = mock(MetricsConfiguration.class);

return new JsonRpcMethodsFactory()
.methods(
Expand All @@ -106,6 +111,9 @@ public Map<String, JsonRpcMethod> methods() {
accountWhitelistController,
nodeWhitelistController,
RpcApis.DEFAULT_JSON_RPC_APIS,
privacyParameters);
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetEnode;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetListening;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetPeerCount;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetServices;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.NetVersion;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.RpcModules;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.TxPoolPantheonTransactions;
Expand All @@ -94,6 +95,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.processor.TransactionTracer;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.BlockResultFactory;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
Expand All @@ -104,6 +106,7 @@
import tech.pegasys.pantheon.ethereum.transaction.TransactionSimulator;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.util.Collection;
import java.util.HashMap;
Expand Down Expand Up @@ -133,7 +136,10 @@ public Map<String, JsonRpcMethod> methods(
final FilterManager filterManager,
final Optional<AccountWhitelistController> accountsWhitelistController,
final Optional<NodeLocalConfigPermissioningController> nodeWhitelistController,
final PrivacyParameters privacyParameters) {
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration) {
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, worldStateArchive);
return methods(
Expand All @@ -152,7 +158,10 @@ public Map<String, JsonRpcMethod> methods(
accountsWhitelistController,
nodeWhitelistController,
rpcApis,
privacyParameters);
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration);
}

public Map<String, JsonRpcMethod> methods(
Expand All @@ -171,7 +180,10 @@ public Map<String, JsonRpcMethod> methods(
final Optional<AccountWhitelistController> accountsWhitelistController,
final Optional<NodeLocalConfigPermissioningController> nodeWhitelistController,
final Collection<RpcApi> rpcApis,
final PrivacyParameters privacyParameters) {
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration) {
final Map<String, JsonRpcMethod> enabledMethods = new HashMap<>();
if (!rpcApis.isEmpty()) {
addMethods(enabledMethods, new RpcModules(rpcApis));
Expand Down Expand Up @@ -256,7 +268,9 @@ blockchainQueries, new TransactionTracer(blockReplay), parameter),
new NetVersion(protocolSchedule.getChainId()),
new NetListening(p2pNetwork),
new NetPeerCount(p2pNetwork),
new NetEnode(p2pNetwork));
new NetEnode(p2pNetwork),
new NetServices(
jsonRpcConfiguration, webSocketConfiguration, p2pNetwork, metricsConfiguration));
}
if (rpcApis.contains(RpcApis.WEB3)) {
addMethods(enabledMethods, new Web3ClientVersion(clientVersion), new Web3Sha3());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2018 ConsenSys AG.
*
* 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.
*/
package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods;

import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import com.google.common.collect.ImmutableMap;

public class NetServices implements JsonRpcMethod {

private final ImmutableMap<String, ImmutableMap<String, String>> services;

public NetServices(
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final P2PNetwork p2pNetwork,
final MetricsConfiguration metricsConfiguration) {

ImmutableMap.Builder<String, ImmutableMap<String, String>> servicesMapBuilder =
ImmutableMap.builder();

if (jsonRpcConfiguration.isEnabled()) {
servicesMapBuilder.put(
"jsonrpc",
createServiceDetailsMap(jsonRpcConfiguration.getHost(), jsonRpcConfiguration.getPort()));
}
if (webSocketConfiguration.isEnabled()) {
servicesMapBuilder.put(
"ws",
createServiceDetailsMap(
webSocketConfiguration.getHost(), webSocketConfiguration.getPort()));
}
if (p2pNetwork.isP2pEnabled()) {
if (p2pNetwork.isP2pEnabled()) {
p2pNetwork
.getLocalEnode()
.ifPresent(
enode -> {
servicesMapBuilder.put(
"p2p", createServiceDetailsMap(enode.getIp(), enode.getListeningPort()));
});
}
}
if (metricsConfiguration.isEnabled()) {
servicesMapBuilder.put(
"metrics",
createServiceDetailsMap(metricsConfiguration.getHost(), metricsConfiguration.getPort()));
}

services = servicesMapBuilder.build();
}

@Override
public String getName() {
return "net_services";
}

@Override
public JsonRpcResponse response(final JsonRpcRequest req) {
return new JsonRpcSuccessResponse(req.getId(), services);
}

private ImmutableMap<String, String> createServiceDetailsMap(final String host, final int port) {
return ImmutableMap.of("host", host, "port", String.valueOf(port));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterRepository;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
Expand All @@ -49,6 +50,7 @@
import tech.pegasys.pantheon.ethereum.util.RawBlockIterator;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.net.URL;
import java.nio.file.Paths;
Expand Down Expand Up @@ -170,6 +172,7 @@ public void setupTest() throws Exception {
supportedCapabilities.add(EthProtocol.ETH62);
supportedCapabilities.add(EthProtocol.ETH63);

final JsonRpcConfiguration config = JsonRpcConfiguration.createDefault();
final Map<String, JsonRpcMethod> methods =
new JsonRpcMethodsFactory()
.methods(
Expand All @@ -188,8 +191,11 @@ public void setupTest() throws Exception {
Optional.empty(),
Optional.empty(),
JSON_RPC_APIS,
privacyParameters);
final JsonRpcConfiguration config = JsonRpcConfiguration.createDefault();
privacyParameters,
config,
mock(WebSocketConfiguration.class),
mock(MetricsConfiguration.class));

config.setPort(0);
service =
new JsonRpcHttpService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterManager;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.io.IOException;
import java.util.Arrays;
Expand Down Expand Up @@ -102,7 +104,10 @@ public void initServerAndClient() throws Exception {
Optional.of(mock(AccountWhitelistController.class)),
Optional.of(mock(NodeLocalConfigPermissioningController.class)),
JSON_RPC_APIS,
mock(PrivacyParameters.class)));
mock(PrivacyParameters.class),
mock(JsonRpcConfiguration.class),
mock(WebSocketConfiguration.class),
mock(MetricsConfiguration.class)));
service = createJsonRpcHttpService();
service.start().join();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.Web3ClientVersion;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.Web3Sha3;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.io.ByteArrayInputStream;
import java.io.IOException;
Expand Down Expand Up @@ -132,7 +134,10 @@ public static void initServerAndClient() throws Exception {
Optional.empty(),
Optional.empty(),
JSON_RPC_APIS,
mock(PrivacyParameters.class)));
mock(PrivacyParameters.class),
mock(JsonRpcConfiguration.class),
mock(WebSocketConfiguration.class),
mock(MetricsConfiguration.class)));
service = createJsonRpcHttpService();
jwtAuth = service.authenticationService.get().getJwtAuthProvider();
service.start().join();
Expand Down
Loading

0 comments on commit 318c41b

Please sign in to comment.