In process RPC service (#7395)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/7416/head
Fabio Di Fabio 4 months ago committed by GitHub
parent 9d92ae87df
commit a7ab1773e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  3. 9
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  4. 8
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java
  5. 11
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  6. 17
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java
  7. 12
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java
  8. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java
  9. 42
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/miner/MinerGetMinGasPriceTransaction.java
  10. 5
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/miner/MinerRequestFactory.java
  11. 4
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/miner/MinerTransactions.java
  12. 81
      acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestInProcessRpcServicePlugin.java
  13. 51
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/InProcessRpcServicePluginTest.java
  14. 15
      besu/src/main/java/org/hyperledger/besu/Runner.java
  15. 46
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  16. 12
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  17. 73
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/InProcessRpcOptions.java
  18. 61
      besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java
  19. 7
      besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java
  20. 2
      besu/src/test/java/org/hyperledger/besu/RunnerTest.java
  21. 1
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  22. 36
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/InProcessRpcConfiguration.java
  23. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcResponse.java
  24. 2
      plugin-api/build.gradle
  25. 10
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/RpcEndpointService.java
  26. 2
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.java
  27. 27
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcResponse.java
  28. 26
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/RpcResponse.java

@ -14,6 +14,7 @@
### Additions and Improvements ### Additions and Improvements
- Expose set finalized/safe block in plugin api BlockchainService. These method can be used by plugins to set finalized/safe block for a PoA network (such as QBFT, IBFT and Clique).[#7382](https://github.com/hyperledger/besu/pull/7382) - Expose set finalized/safe block in plugin api BlockchainService. These method can be used by plugins to set finalized/safe block for a PoA network (such as QBFT, IBFT and Clique).[#7382](https://github.com/hyperledger/besu/pull/7382)
- In process RPC service [#7395](https://github.com/hyperledger/besu/pull/7395)
### Bug fixes ### Bug fixes

@ -23,6 +23,7 @@ import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.KeyPairUtil; import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -109,6 +110,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private final Optional<JsonRpcConfiguration> engineRpcConfiguration; private final Optional<JsonRpcConfiguration> engineRpcConfiguration;
private final WebSocketConfiguration webSocketConfiguration; private final WebSocketConfiguration webSocketConfiguration;
private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration;
private final InProcessRpcConfiguration inProcessRpcConfiguration;
private final MetricsConfiguration metricsConfiguration; private final MetricsConfiguration metricsConfiguration;
private final DataStorageConfiguration dataStorageConfiguration; private final DataStorageConfiguration dataStorageConfiguration;
private Optional<PermissioningConfiguration> permissioningConfiguration; private Optional<PermissioningConfiguration> permissioningConfiguration;
@ -143,6 +145,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final Optional<JsonRpcConfiguration> engineRpcConfiguration, final Optional<JsonRpcConfiguration> engineRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration, final WebSocketConfiguration webSocketConfiguration,
final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final JsonRpcIpcConfiguration jsonRpcIpcConfiguration,
final InProcessRpcConfiguration inProcessRpcConfiguration,
final MetricsConfiguration metricsConfiguration, final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration, final Optional<PermissioningConfiguration> permissioningConfiguration,
final ApiConfiguration apiConfiguration, final ApiConfiguration apiConfiguration,
@ -193,6 +196,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.engineRpcConfiguration = engineRpcConfiguration; this.engineRpcConfiguration = engineRpcConfiguration;
this.webSocketConfiguration = webSocketConfiguration; this.webSocketConfiguration = webSocketConfiguration;
this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration;
this.inProcessRpcConfiguration = inProcessRpcConfiguration;
this.metricsConfiguration = metricsConfiguration; this.metricsConfiguration = metricsConfiguration;
this.permissioningConfiguration = permissioningConfiguration; this.permissioningConfiguration = permissioningConfiguration;
this.apiConfiguration = apiConfiguration; this.apiConfiguration = apiConfiguration;
@ -624,6 +628,10 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return jsonRpcIpcConfiguration; return jsonRpcIpcConfiguration;
} }
InProcessRpcConfiguration inProcessRpcConfiguration() {
return inProcessRpcConfiguration;
}
Optional<String> wsRpcListenHost() { Optional<String> wsRpcListenHost() {
return Optional.of(webSocketConfiguration().getHost()); return Optional.of(webSocketConfiguration().getHost());
} }

@ -29,6 +29,7 @@ import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration; import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
@ -236,6 +237,8 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.transactionPoolValidatorService(transactionPoolValidatorServiceImpl) .transactionPoolValidatorService(transactionPoolValidatorServiceImpl)
.build(); .build();
final InProcessRpcConfiguration inProcessRpcConfiguration = node.inProcessRpcConfiguration();
final int maxPeers = 25; final int maxPeers = 25;
builder builder
@ -297,7 +300,8 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.besuPluginContext(besuPluginContext) .besuPluginContext(besuPluginContext)
.autoLogBloomCaching(false) .autoLogBloomCaching(false)
.storageProvider(storageProvider) .storageProvider(storageProvider)
.rpcEndpointService(rpcEndpointServiceImpl); .rpcEndpointService(rpcEndpointServiceImpl)
.inProcessRpcConfiguration(inProcessRpcConfiguration);
node.engineRpcConfiguration().ifPresent(runnerBuilder::engineJsonRpcConfiguration); node.engineRpcConfiguration().ifPresent(runnerBuilder::engineJsonRpcConfiguration);
besuPluginContext.beforeExternalServices(); besuPluginContext.beforeExternalServices();
@ -313,6 +317,9 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
besuController.getTransactionPool(), besuController.getTransactionPool(),
besuController.getSyncState(), besuController.getSyncState(),
besuController.getProtocolContext().getBadBlockManager())); besuController.getProtocolContext().getBadBlockManager()));
rpcEndpointServiceImpl.init(runner.getInProcessRpcMethods());
besuPluginContext.startPlugins(); besuPluginContext.startPlugins();
runner.startEthereumMainLoop(); runner.startEthereumMainLoop();

@ -17,6 +17,7 @@ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration;
import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -45,6 +46,7 @@ public class BesuNodeConfiguration {
private final Optional<JsonRpcConfiguration> engineRpcConfiguration; private final Optional<JsonRpcConfiguration> engineRpcConfiguration;
private final WebSocketConfiguration webSocketConfiguration; private final WebSocketConfiguration webSocketConfiguration;
private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private final JsonRpcIpcConfiguration jsonRpcIpcConfiguration;
private final InProcessRpcConfiguration inProcessRpcConfiguration;
private final MetricsConfiguration metricsConfiguration; private final MetricsConfiguration metricsConfiguration;
private final Optional<PermissioningConfiguration> permissioningConfiguration; private final Optional<PermissioningConfiguration> permissioningConfiguration;
private final ApiConfiguration apiConfiguration; private final ApiConfiguration apiConfiguration;
@ -81,6 +83,7 @@ public class BesuNodeConfiguration {
final Optional<JsonRpcConfiguration> engineRpcConfiguration, final Optional<JsonRpcConfiguration> engineRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration, final WebSocketConfiguration webSocketConfiguration,
final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final JsonRpcIpcConfiguration jsonRpcIpcConfiguration,
final InProcessRpcConfiguration inProcessRpcConfiguration,
final MetricsConfiguration metricsConfiguration, final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration, final Optional<PermissioningConfiguration> permissioningConfiguration,
final ApiConfiguration apiConfiguration, final ApiConfiguration apiConfiguration,
@ -114,6 +117,7 @@ public class BesuNodeConfiguration {
this.engineRpcConfiguration = engineRpcConfiguration; this.engineRpcConfiguration = engineRpcConfiguration;
this.webSocketConfiguration = webSocketConfiguration; this.webSocketConfiguration = webSocketConfiguration;
this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration; this.jsonRpcIpcConfiguration = jsonRpcIpcConfiguration;
this.inProcessRpcConfiguration = inProcessRpcConfiguration;
this.metricsConfiguration = metricsConfiguration; this.metricsConfiguration = metricsConfiguration;
this.permissioningConfiguration = permissioningConfiguration; this.permissioningConfiguration = permissioningConfiguration;
this.apiConfiguration = apiConfiguration; this.apiConfiguration = apiConfiguration;
@ -171,6 +175,10 @@ public class BesuNodeConfiguration {
return jsonRpcIpcConfiguration; return jsonRpcIpcConfiguration;
} }
public InProcessRpcConfiguration getInProcessRpcConfiguration() {
return inProcessRpcConfiguration;
}
public MetricsConfiguration getMetricsConfiguration() { public MetricsConfiguration getMetricsConfiguration() {
return metricsConfiguration; return metricsConfiguration;
} }

@ -24,6 +24,8 @@ import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ImmutableInProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm;
@ -70,6 +72,8 @@ public class BesuNodeConfigurationBuilder {
private JsonRpcConfiguration engineRpcConfiguration = JsonRpcConfiguration.createEngineDefault(); private JsonRpcConfiguration engineRpcConfiguration = JsonRpcConfiguration.createEngineDefault();
private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault(); private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault();
private JsonRpcIpcConfiguration jsonRpcIpcConfiguration = new JsonRpcIpcConfiguration(); private JsonRpcIpcConfiguration jsonRpcIpcConfiguration = new JsonRpcIpcConfiguration();
private InProcessRpcConfiguration inProcessRpcConfiguration =
ImmutableInProcessRpcConfiguration.builder().build();
private MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder().build(); private MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder().build();
private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty(); private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty();
private ApiConfiguration apiConfiguration = ImmutableApiConfiguration.builder().build(); private ApiConfiguration apiConfiguration = ImmutableApiConfiguration.builder().build();
@ -258,6 +262,12 @@ public class BesuNodeConfigurationBuilder {
return this; return this;
} }
public BesuNodeConfigurationBuilder inProcessRpcConfiguration(
final InProcessRpcConfiguration inProcessRpcConfiguration) {
this.inProcessRpcConfiguration = inProcessRpcConfiguration;
return this;
}
public BesuNodeConfigurationBuilder metricsConfiguration( public BesuNodeConfigurationBuilder metricsConfiguration(
final MetricsConfiguration metricsConfiguration) { final MetricsConfiguration metricsConfiguration) {
this.metricsConfiguration = metricsConfiguration; this.metricsConfiguration = metricsConfiguration;
@ -516,6 +526,7 @@ public class BesuNodeConfigurationBuilder {
Optional.of(engineRpcConfiguration), Optional.of(engineRpcConfiguration),
webSocketConfiguration, webSocketConfiguration,
jsonRpcIpcConfiguration, jsonRpcIpcConfiguration,
inProcessRpcConfiguration,
metricsConfiguration, metricsConfiguration,
permissioningConfiguration, permissioningConfiguration,
apiConfiguration, apiConfiguration,

@ -16,6 +16,8 @@ package org.hyperledger.besu.tests.acceptance.dsl.node.configuration;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ADMIN;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.IBFT;
import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
@ -43,6 +45,7 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -64,6 +67,7 @@ public class BesuNodeFactory {
config.getEngineRpcConfiguration(), config.getEngineRpcConfiguration(),
config.getWebSocketConfiguration(), config.getWebSocketConfiguration(),
config.getJsonRpcIpcConfiguration(), config.getJsonRpcIpcConfiguration(),
config.getInProcessRpcConfiguration(),
config.getMetricsConfiguration(), config.getMetricsConfiguration(),
config.getPermissioningConfiguration(), config.getPermissioningConfiguration(),
config.getApiConfiguration(), config.getApiConfiguration(),
@ -330,12 +334,20 @@ public class BesuNodeFactory {
} }
public BesuNode createPluginsNode( public BesuNode createPluginsNode(
final String name, final List<String> plugins, final List<String> extraCLIOptions) final String name,
final List<String> plugins,
final List<String> extraCLIOptions,
final String... extraRpcApis)
throws IOException { throws IOException {
final List<String> enableRpcApis = new ArrayList<>(Arrays.asList(extraRpcApis));
enableRpcApis.addAll(List.of(IBFT.name(), ADMIN.name()));
return create( return create(
new BesuNodeConfigurationBuilder() new BesuNodeConfigurationBuilder()
.name(name) .name(name)
.jsonRpcConfiguration(node.createJsonRpcWithIbft2AdminEnabledConfig()) .jsonRpcConfiguration(
node.createJsonRpcWithRpcApiEnabledConfig(enableRpcApis.toArray(String[]::new)))
.webSocketConfiguration(node.createWebSocketEnabledConfig()) .webSocketConfiguration(node.createWebSocketEnabledConfig())
.plugins(plugins) .plugins(plugins)
.extraCLIOptions(extraCLIOptions) .extraCLIOptions(extraCLIOptions)
@ -394,6 +406,7 @@ public class BesuNodeFactory {
.miningEnabled() .miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig(extraRpcApis)) .jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig(extraRpcApis))
.webSocketConfiguration(node.createWebSocketEnabledConfig()) .webSocketConfiguration(node.createWebSocketEnabledConfig())
.inProcessRpcConfiguration(node.createInProcessRpcConfiguration(extraRpcApis))
.devMode(false) .devMode(false)
.jsonRpcTxPool() .jsonRpcTxPool()
.genesisConfigProvider( .genesisConfigProvider(

@ -22,6 +22,8 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.IBFT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.MINER; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.MINER;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.QBFT; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.QBFT;
import org.hyperledger.besu.ethereum.api.jsonrpc.ImmutableInProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
@ -94,4 +96,14 @@ public class NodeConfigurationFactory {
jsonRpcConfig.setRpcApis(rpcApis); jsonRpcConfig.setRpcApis(rpcApis);
return jsonRpcConfig; return jsonRpcConfig;
} }
public InProcessRpcConfiguration createInProcessRpcConfiguration(final Set<String> extraRpcApis) {
final Set<String> rpcApis =
new HashSet<>(ImmutableInProcessRpcConfiguration.DEFAULT_IN_PROCESS_RPC_APIS);
rpcApis.addAll(extraRpcApis);
return ImmutableInProcessRpcConfiguration.builder()
.inProcessRpcApis(rpcApis)
.isEnabled(true)
.build();
}
} }

@ -106,6 +106,7 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.getEngineRpcConfiguration(), besuConfig.getEngineRpcConfiguration(),
besuConfig.getWebSocketConfiguration(), besuConfig.getWebSocketConfiguration(),
besuConfig.getJsonRpcIpcConfiguration(), besuConfig.getJsonRpcIpcConfiguration(),
besuConfig.getInProcessRpcConfiguration(),
besuConfig.getMetricsConfiguration(), besuConfig.getMetricsConfiguration(),
besuConfig.getPermissioningConfiguration(), besuConfig.getPermissioningConfiguration(),
besuConfig.getApiConfiguration(), besuConfig.getApiConfiguration(),

@ -0,0 +1,42 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.tests.acceptance.dsl.transaction.miner;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.web3j.protocol.core.methods.response.EthGasPrice;
public class MinerGetMinGasPriceTransaction implements Transaction<BigInteger> {
@Override
public BigInteger execute(final NodeRequests node) {
try {
final EthGasPrice result = node.miner().minerGetMinGasPrice().send();
assertThat(result).isNotNull();
assertThat(result.hasError()).isFalse();
return result.getGasPrice();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -16,6 +16,7 @@ package org.hyperledger.besu.tests.acceptance.dsl.transaction.miner;
import org.web3j.protocol.Web3jService; import org.web3j.protocol.Web3jService;
import org.web3j.protocol.core.Request; import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.response.EthGasPrice;
public class MinerRequestFactory { public class MinerRequestFactory {
@ -40,4 +41,8 @@ public class MinerRequestFactory {
web3jService, web3jService,
org.web3j.protocol.core.methods.response.VoidResponse.class); org.web3j.protocol.core.methods.response.VoidResponse.class);
} }
Request<?, EthGasPrice> minerGetMinGasPrice() {
return new Request<>("miner_getMinGasPrice", null, web3jService, EthGasPrice.class);
}
} }

@ -23,4 +23,8 @@ public class MinerTransactions {
public MinerStopTransaction minerStop() { public MinerStopTransaction minerStop() {
return new MinerStopTransaction(); return new MinerStopTransaction();
} }
public MinerGetMinGasPriceTransaction minerGetMinGasPrice() {
return new MinerGetMinGasPriceTransaction();
}
} }

@ -0,0 +1,81 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.tests.acceptance.plugins;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.BesuPlugin;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
import org.hyperledger.besu.plugin.services.RpcEndpointService;
import org.hyperledger.besu.plugin.services.rpc.RpcResponseType;
import com.google.auto.service.AutoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
@AutoService(BesuPlugin.class)
public class TestInProcessRpcServicePlugin implements BesuPlugin {
private static final Logger LOG = LoggerFactory.getLogger(TestInProcessRpcServicePlugin.class);
private RpcEndpointService rpcEndpointService;
@CommandLine.Option(names = {"--plugin-test-set-min-gas-price"})
long minGasPrice = -1;
@Override
public void register(final BesuContext context) {
final PicoCLIOptions cmdlineOptions =
context
.getService(PicoCLIOptions.class)
.orElseThrow(
() ->
new IllegalStateException(
"Failed to obtain PicoCLI options from the BesuContext"));
cmdlineOptions.addPicoCLIOptions("test", this);
rpcEndpointService =
context
.getService(RpcEndpointService.class)
.orElseThrow(
() ->
new RuntimeException(
"Failed to obtain RpcEndpointService from the BesuContext."));
}
@Override
public void start() {
LOG.info("TestInProcessRpcServicePlugin minGasPrice option: {}", minGasPrice);
if (minGasPrice >= 0) {
callSetMinGasPrice(minGasPrice);
}
}
@Override
public void stop() {}
private void callSetMinGasPrice(final long minGasPrice) {
LOG.info("Setting minGasPrice via in-process RPC service");
final var minGasPriceWei = Wei.of(minGasPrice);
final var resp =
rpcEndpointService.call(
"miner_setMinGasPrice", new Object[] {minGasPriceWei.toShortHexString()});
LOG.info("miner_setMinGasPrice response: {}", resp);
if (!resp.getType().equals(RpcResponseType.SUCCESS)) {
throw new RuntimeException("Internal setMinGasPrice method failed: " + resp);
}
}
}

@ -0,0 +1,51 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.tests.acceptance.plugins;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import java.math.BigInteger;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class InProcessRpcServicePluginTest extends AcceptanceTestBase {
private static final long MIN_GAS_PRICE = 123456;
private BesuNode node;
@BeforeEach
public void setUp() throws Exception {
node =
besu.createPluginsNode(
"node1",
List.of("testPlugins"),
List.of(
"--Xin-process-rpc-enabled=true",
"--Xin-process-rpc-apis=MINER",
"--plugin-test-set-min-gas-price=" + MIN_GAS_PRICE),
"MINER");
cluster.start(node);
}
@Test
public void smokeTest() {
final var currMinGasPrice = node.execute(minerTransactions.minerGetMinGasPrice());
assertThat(currMinGasPrice).isEqualTo(BigInteger.valueOf(MIN_GAS_PRICE));
}
}

@ -18,6 +18,7 @@ import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService; import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService;
import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcService;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketService; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketService;
import org.hyperledger.besu.ethereum.api.query.cache.AutoTransactionLogBloomCachingService; import org.hyperledger.besu.ethereum.api.query.cache.AutoTransactionLogBloomCachingService;
@ -39,6 +40,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -69,6 +71,7 @@ public class Runner implements AutoCloseable {
private final Optional<EngineJsonRpcService> engineJsonRpc; private final Optional<EngineJsonRpcService> engineJsonRpc;
private final Optional<MetricsService> metrics; private final Optional<MetricsService> metrics;
private final Optional<JsonRpcIpcService> ipcJsonRpc; private final Optional<JsonRpcIpcService> ipcJsonRpc;
private final Map<String, JsonRpcMethod> inProcessRpcMethods;
private final Optional<Path> pidPath; private final Optional<Path> pidPath;
private final Optional<WebSocketService> webSocketRpc; private final Optional<WebSocketService> webSocketRpc;
private final TransactionPoolEvictionService transactionPoolEvictionService; private final TransactionPoolEvictionService transactionPoolEvictionService;
@ -90,6 +93,7 @@ public class Runner implements AutoCloseable {
* @param graphQLHttp the graph ql http * @param graphQLHttp the graph ql http
* @param webSocketRpc the web socket rpc * @param webSocketRpc the web socket rpc
* @param ipcJsonRpc the ipc json rpc * @param ipcJsonRpc the ipc json rpc
* @param inProcessRpcMethods the in-process rpc methods
* @param stratumServer the stratum server * @param stratumServer the stratum server
* @param metrics the metrics * @param metrics the metrics
* @param ethStatsService the eth stats service * @param ethStatsService the eth stats service
@ -108,6 +112,7 @@ public class Runner implements AutoCloseable {
final Optional<GraphQLHttpService> graphQLHttp, final Optional<GraphQLHttpService> graphQLHttp,
final Optional<WebSocketService> webSocketRpc, final Optional<WebSocketService> webSocketRpc,
final Optional<JsonRpcIpcService> ipcJsonRpc, final Optional<JsonRpcIpcService> ipcJsonRpc,
final Map<String, JsonRpcMethod> inProcessRpcMethods,
final Optional<StratumServer> stratumServer, final Optional<StratumServer> stratumServer,
final Optional<MetricsService> metrics, final Optional<MetricsService> metrics,
final Optional<EthStatsService> ethStatsService, final Optional<EthStatsService> ethStatsService,
@ -125,6 +130,7 @@ public class Runner implements AutoCloseable {
this.engineJsonRpc = engineJsonRpc; this.engineJsonRpc = engineJsonRpc;
this.webSocketRpc = webSocketRpc; this.webSocketRpc = webSocketRpc;
this.ipcJsonRpc = ipcJsonRpc; this.ipcJsonRpc = ipcJsonRpc;
this.inProcessRpcMethods = inProcessRpcMethods;
this.metrics = metrics; this.metrics = metrics;
this.ethStatsService = ethStatsService; this.ethStatsService = ethStatsService;
this.besuController = besuController; this.besuController = besuController;
@ -413,6 +419,15 @@ public class Runner implements AutoCloseable {
} }
} }
/**
* Get the RPC methods that can be called in-process
*
* @return RPC methods by name
*/
public Map<String, JsonRpcMethod> getInProcessRpcMethods() {
return inProcessRpcMethods;
}
/** /**
* Gets local enode. * Gets local enode.
* *

@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLDataFetchers;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService; import org.hyperledger.besu.ethereum.api.graphql.GraphQLHttpService;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLProvider; import org.hyperledger.besu.ethereum.api.graphql.GraphQLProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService; import org.hyperledger.besu.ethereum.api.jsonrpc.EngineJsonRpcService;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService;
import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.AuthenticationService; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.AuthenticationService;
@ -178,6 +179,7 @@ public class RunnerBuilder {
private Optional<JsonRpcConfiguration> engineJsonRpcConfiguration = Optional.empty(); private Optional<JsonRpcConfiguration> engineJsonRpcConfiguration = Optional.empty();
private GraphQLConfiguration graphQLConfiguration; private GraphQLConfiguration graphQLConfiguration;
private WebSocketConfiguration webSocketConfiguration; private WebSocketConfiguration webSocketConfiguration;
private InProcessRpcConfiguration inProcessRpcConfiguration;
private ApiConfiguration apiConfiguration; private ApiConfiguration apiConfiguration;
private Path dataDir; private Path dataDir;
private Optional<Path> pidPath = Optional.empty(); private Optional<Path> pidPath = Optional.empty();
@ -414,6 +416,18 @@ public class RunnerBuilder {
return this; return this;
} }
/**
* Add In-Process RPC configuration.
*
* @param inProcessRpcConfiguration the in-process RPC configuration
* @return the runner builder
*/
public RunnerBuilder inProcessRpcConfiguration(
final InProcessRpcConfiguration inProcessRpcConfiguration) {
this.inProcessRpcConfiguration = inProcessRpcConfiguration;
return this;
}
/** /**
* Add Api configuration. * Add Api configuration.
* *
@ -1082,6 +1096,37 @@ public class RunnerBuilder {
jsonRpcIpcService = Optional.empty(); jsonRpcIpcService = Optional.empty();
} }
final Map<String, JsonRpcMethod> inProcessRpcMethods;
if (inProcessRpcConfiguration.isEnabled()) {
inProcessRpcMethods =
jsonRpcMethods(
protocolSchedule,
context,
besuController,
peerNetwork,
blockchainQueries,
synchronizer,
transactionPool,
miningParameters,
miningCoordinator,
metricsSystem,
supportedCapabilities,
inProcessRpcConfiguration.getInProcessRpcApis(),
filterManager,
accountLocalConfigPermissioningController,
nodeLocalConfigPermissioningController,
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,
natService,
besuPluginContext.getNamedPlugins(),
dataDir,
rpcEndpointServiceImpl);
} else {
inProcessRpcMethods = Map.of();
}
return new Runner( return new Runner(
vertx, vertx,
networkRunner, networkRunner,
@ -1091,6 +1136,7 @@ public class RunnerBuilder {
graphQLHttpService, graphQLHttpService,
webSocketService, webSocketService,
jsonRpcIpcService, jsonRpcIpcService,
inProcessRpcMethods,
stratumServer, stratumServer,
metricsService, metricsService,
ethStatsService, ethStatsService,

@ -63,6 +63,7 @@ import org.hyperledger.besu.cli.options.unstable.ChainPruningOptions;
import org.hyperledger.besu.cli.options.unstable.DnsOptions; import org.hyperledger.besu.cli.options.unstable.DnsOptions;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions; import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
import org.hyperledger.besu.cli.options.unstable.EvmOptions; import org.hyperledger.besu.cli.options.unstable.EvmOptions;
import org.hyperledger.besu.cli.options.unstable.InProcessRpcOptions;
import org.hyperledger.besu.cli.options.unstable.IpcOptions; import org.hyperledger.besu.cli.options.unstable.IpcOptions;
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions; import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
import org.hyperledger.besu.cli.options.unstable.NatOptions; import org.hyperledger.besu.cli.options.unstable.NatOptions;
@ -107,6 +108,7 @@ import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm;
@ -660,6 +662,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
@CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC Websocket Options|@%n") @CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC Websocket Options|@%n")
RpcWebsocketOptions rpcWebsocketOptions = new RpcWebsocketOptions(); RpcWebsocketOptions rpcWebsocketOptions = new RpcWebsocketOptions();
// In-Process RPC Options
@CommandLine.ArgGroup(validate = false, heading = "@|bold In-Process RPC Options|@%n")
InProcessRpcOptions inProcessRpcOptions = InProcessRpcOptions.create();
// Privacy Options Group // Privacy Options Group
@CommandLine.ArgGroup(validate = false, heading = "@|bold Privacy Options|@%n") @CommandLine.ArgGroup(validate = false, heading = "@|bold Privacy Options|@%n")
PrivacyOptionGroup privacyOptionGroup = new PrivacyOptionGroup(); PrivacyOptionGroup privacyOptionGroup = new PrivacyOptionGroup();
@ -926,6 +932,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private GraphQLConfiguration graphQLConfiguration; private GraphQLConfiguration graphQLConfiguration;
private WebSocketConfiguration webSocketConfiguration; private WebSocketConfiguration webSocketConfiguration;
private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private JsonRpcIpcConfiguration jsonRpcIpcConfiguration;
private InProcessRpcConfiguration inProcessRpcConfiguration;
private ApiConfiguration apiConfiguration; private ApiConfiguration apiConfiguration;
private MetricsConfiguration metricsConfiguration; private MetricsConfiguration metricsConfiguration;
private Optional<PermissioningConfiguration> permissioningConfiguration; private Optional<PermissioningConfiguration> permissioningConfiguration;
@ -1353,6 +1360,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
engineJsonRpcConfiguration, engineJsonRpcConfiguration,
webSocketConfiguration, webSocketConfiguration,
jsonRpcIpcConfiguration, jsonRpcIpcConfiguration,
inProcessRpcConfiguration,
apiConfiguration, apiConfiguration,
metricsConfiguration, metricsConfiguration,
permissioningConfiguration, permissioningConfiguration,
@ -1370,6 +1378,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuController.getProtocolContext().getWorldStateArchive(), besuController.getProtocolContext().getWorldStateArchive(),
besuController.getProtocolSchedule(), besuController.getProtocolSchedule(),
apiConfiguration.getGasCap())); apiConfiguration.getGasCap()));
rpcEndpointServiceImpl.init(runner.getInProcessRpcMethods());
besuPluginContext.addService( besuPluginContext.addService(
BesuEvents.class, BesuEvents.class,
@ -1810,6 +1819,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
unstableIpcOptions.isEnabled(), unstableIpcOptions.isEnabled(),
unstableIpcOptions.getIpcPath(), unstableIpcOptions.getIpcPath(),
unstableIpcOptions.getRpcIpcApis()); unstableIpcOptions.getRpcIpcApis());
inProcessRpcConfiguration = inProcessRpcOptions.toDomainObject();
apiConfiguration = apiConfigurationOptions.apiConfiguration(); apiConfiguration = apiConfigurationOptions.apiConfiguration();
dataStorageConfiguration = getDataStorageConfiguration(); dataStorageConfiguration = getDataStorageConfiguration();
// hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist // hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist
@ -2321,6 +2331,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final JsonRpcConfiguration engineJsonRpcConfiguration, final JsonRpcConfiguration engineJsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration, final WebSocketConfiguration webSocketConfiguration,
final JsonRpcIpcConfiguration jsonRpcIpcConfiguration, final JsonRpcIpcConfiguration jsonRpcIpcConfiguration,
final InProcessRpcConfiguration inProcessRpcConfiguration,
final ApiConfiguration apiConfiguration, final ApiConfiguration apiConfiguration,
final MetricsConfiguration metricsConfiguration, final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration, final Optional<PermissioningConfiguration> permissioningConfiguration,
@ -2353,6 +2364,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.engineJsonRpcConfiguration(engineJsonRpcConfiguration) .engineJsonRpcConfiguration(engineJsonRpcConfiguration)
.webSocketConfiguration(webSocketConfiguration) .webSocketConfiguration(webSocketConfiguration)
.jsonRpcIpcConfiguration(jsonRpcIpcConfiguration) .jsonRpcIpcConfiguration(jsonRpcIpcConfiguration)
.inProcessRpcConfiguration(inProcessRpcConfiguration)
.apiConfiguration(apiConfiguration) .apiConfiguration(apiConfiguration)
.pidPath(pidPath) .pidPath(pidPath)
.dataDir(dataDir()) .dataDir(dataDir())

@ -0,0 +1,73 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.cli.options.unstable;
import static org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration.DEFAULT_IN_PROCESS_RPC_APIS;
import static org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration.DEFAULT_IN_PROCESS_RPC_ENABLED;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.ethereum.api.jsonrpc.ImmutableInProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import java.util.List;
import java.util.Set;
import picocli.CommandLine;
/** The in process RPC options. */
public class InProcessRpcOptions implements CLIOptions<InProcessRpcConfiguration> {
/** Default constructor. */
InProcessRpcOptions() {}
/**
* Create ipc options.
*
* @return the ipc options
*/
public static InProcessRpcOptions create() {
return new InProcessRpcOptions();
}
@CommandLine.Option(
names = {"--Xin-process-rpc-enabled"},
hidden = true,
description = "Set to enalbe in-process RPC method call service (default: ${DEFAULT-VALUE})")
private final Boolean enabled = DEFAULT_IN_PROCESS_RPC_ENABLED;
@CommandLine.Option(
names = {"--Xin-process-rpc-api", "--Xin-process-rpc-apis"},
hidden = true,
paramLabel = "<api name>",
split = " {0,1}, {0,1}",
arity = "1..*",
description =
"Comma separated list of APIs to enable on in-process RPC method call service (default: ${DEFAULT-VALUE})")
private final Set<String> inProcessRpcApis = DEFAULT_IN_PROCESS_RPC_APIS;
@Override
public InProcessRpcConfiguration toDomainObject() {
return ImmutableInProcessRpcConfiguration.builder()
.isEnabled(enabled)
.inProcessRpcApis(inProcessRpcApis)
.build();
}
@Override
public List<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new InProcessRpcOptions());
}
}

@ -17,25 +17,48 @@ package org.hyperledger.besu.services;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
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.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginJsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginJsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.plugin.services.RpcEndpointService; import org.hyperledger.besu.plugin.services.RpcEndpointService;
import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest;
import org.hyperledger.besu.plugin.services.rpc.PluginRpcResponse;
import org.hyperledger.besu.plugin.services.rpc.RpcResponseType;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** The RPC endpoint service implementation. */ /** The RPC endpoint service implementation. */
public class RpcEndpointServiceImpl implements RpcEndpointService { public class RpcEndpointServiceImpl implements RpcEndpointService {
private static final Logger LOG = LoggerFactory.getLogger(RpcEndpointServiceImpl.class);
private final Map<String, Function<PluginRpcRequest, ?>> rpcMethods = new HashMap<>(); private final Map<String, Function<PluginRpcRequest, ?>> rpcMethods = new HashMap<>();
private Map<String, JsonRpcMethod> inProcessRpcMethods;
/** Default Constructor. */ /** Default Constructor. */
public RpcEndpointServiceImpl() {} public RpcEndpointServiceImpl() {}
/**
* Init the service
*
* @param inProcessRpcMethods set of RPC methods that can be called
*/
public void init(final Map<String, JsonRpcMethod> inProcessRpcMethods) {
this.inProcessRpcMethods = inProcessRpcMethods;
}
@Override @Override
public <T> void registerRPCEndpoint( public <T> void registerRPCEndpoint(
final String namespace, final String namespace,
@ -48,6 +71,44 @@ public class RpcEndpointServiceImpl implements RpcEndpointService {
rpcMethods.put(namespace + "_" + functionName, function); rpcMethods.put(namespace + "_" + functionName, function);
} }
@Override
public PluginRpcResponse call(final String methodName, final Object[] params) {
checkNotNull(
inProcessRpcMethods,
"Service not initialized yet, this method must be called after plugin 'beforeExternalServices' call completes");
LOG.atTrace()
.setMessage("Calling method:{} with params:{}")
.addArgument(methodName)
.addArgument(() -> Arrays.toString(params))
.log();
final var method = inProcessRpcMethods.get(methodName);
if (method == null) {
throw new NoSuchElementException("Unknown or not enabled method: " + methodName);
}
final var requestContext =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", methodName, params));
final var response = method.response(requestContext);
return new PluginRpcResponse() {
@Override
public Object getResult() {
return switch (response.getType()) {
case NONE, UNAUTHORIZED -> null;
case SUCCESS -> ((JsonRpcSuccessResponse) response).getResult();
case ERROR -> ((JsonRpcErrorResponse) response).getError();
};
}
@Override
public RpcResponseType getType() {
return response.getType();
}
};
}
/** /**
* Gets plugin methods. * Gets plugin methods.
* *

@ -38,6 +38,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -163,6 +164,7 @@ public final class RunnerBuilderTest {
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.webSocketConfiguration(mock(WebSocketConfiguration.class)) .webSocketConfiguration(mock(WebSocketConfiguration.class))
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(vertx) .vertx(vertx)
.dataDir(dataDir.getRoot()) .dataDir(dataDir.getRoot())
@ -208,6 +210,7 @@ public final class RunnerBuilderTest {
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.webSocketConfiguration(mock(WebSocketConfiguration.class)) .webSocketConfiguration(mock(WebSocketConfiguration.class))
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx()) .vertx(Vertx.vertx())
.dataDir(dataDir.getRoot()) .dataDir(dataDir.getRoot())
@ -267,6 +270,7 @@ public final class RunnerBuilderTest {
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.webSocketConfiguration(mock(WebSocketConfiguration.class)) .webSocketConfiguration(mock(WebSocketConfiguration.class))
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx()) .vertx(Vertx.vertx())
.dataDir(dataDir.getRoot()) .dataDir(dataDir.getRoot())
@ -309,6 +313,7 @@ public final class RunnerBuilderTest {
.engineJsonRpcConfiguration(engineConf) .engineJsonRpcConfiguration(engineConf)
.webSocketConfiguration(wsRpc) .webSocketConfiguration(wsRpc)
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx()) .vertx(Vertx.vertx())
@ -351,6 +356,7 @@ public final class RunnerBuilderTest {
.engineJsonRpcConfiguration(engineConf) .engineJsonRpcConfiguration(engineConf)
.webSocketConfiguration(wsRpc) .webSocketConfiguration(wsRpc)
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx()) .vertx(Vertx.vertx())
@ -395,6 +401,7 @@ public final class RunnerBuilderTest {
.graphQLConfiguration(mock(GraphQLConfiguration.class)) .graphQLConfiguration(mock(GraphQLConfiguration.class))
.webSocketConfiguration(defaultWebSockConfig) .webSocketConfiguration(defaultWebSockConfig)
.jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class)) .jsonRpcIpcConfiguration(mock(JsonRpcIpcConfiguration.class))
.inProcessRpcConfiguration(mock(InProcessRpcConfiguration.class))
.metricsConfiguration(mock(MetricsConfiguration.class)) .metricsConfiguration(mock(MetricsConfiguration.class))
.vertx(Vertx.vertx()) .vertx(Vertx.vertx())
.dataDir(dataDir.getRoot()) .dataDir(dataDir.getRoot())

@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ImmutableInProcessRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
@ -211,6 +212,7 @@ public final class RunnerTest {
.graphQLConfiguration(graphQLConfiguration()) .graphQLConfiguration(graphQLConfiguration())
.webSocketConfiguration(wsRpcConfiguration()) .webSocketConfiguration(wsRpcConfiguration())
.jsonRpcIpcConfiguration(new JsonRpcIpcConfiguration()) .jsonRpcIpcConfiguration(new JsonRpcIpcConfiguration())
.inProcessRpcConfiguration(ImmutableInProcessRpcConfiguration.builder().build())
.metricsConfiguration(metricsConfiguration()) .metricsConfiguration(metricsConfiguration())
.dataDir(dbAhead) .dataDir(dbAhead)
.pidPath(pidPath) .pidPath(pidPath)

@ -332,6 +332,7 @@ public abstract class CommandTestAbstract {
when(mockRunnerBuilder.graphQLConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.graphQLConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.webSocketConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.webSocketConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.jsonRpcIpcConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.jsonRpcIpcConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.inProcessRpcConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.apiConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.apiConfiguration(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.dataDir(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.dataDir(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.bannedNodeIds(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.bannedNodeIds(any())).thenReturn(mockRunnerBuilder);

@ -0,0 +1,36 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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;
import java.util.HashSet;
import java.util.Set;
import org.immutables.value.Value;
@Value.Immutable
public interface InProcessRpcConfiguration {
boolean DEFAULT_IN_PROCESS_RPC_ENABLED = false;
Set<String> DEFAULT_IN_PROCESS_RPC_APIS = new HashSet<>(RpcApis.DEFAULT_RPC_APIS);
@Value.Default
default boolean isEnabled() {
return DEFAULT_IN_PROCESS_RPC_ENABLED;
}
@Value.Default
default Set<String> getInProcessRpcApis() {
return DEFAULT_IN_PROCESS_RPC_APIS;
}
}

@ -14,16 +14,14 @@
*/ */
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.response; package org.hyperledger.besu.ethereum.api.jsonrpc.internal.response;
import org.hyperledger.besu.plugin.services.rpc.RpcResponseType; import org.hyperledger.besu.plugin.services.rpc.RpcResponse;
import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonGetter;
public interface JsonRpcResponse { public interface JsonRpcResponse extends RpcResponse {
@JsonGetter("jsonrpc") @JsonGetter("jsonrpc")
default String getVersion() { default String getVersion() {
return "2.0"; return "2.0";
} }
RpcResponseType getType();
} }

@ -70,7 +70,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) { tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought" description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files files = sourceSets.main.allJava.files
knownHash = 'tXFd8EcMJtD+ZSLJxWJLYRZD0d3njRz+3Ubey2zFM2A=' knownHash = 'I851CCOs00yYpW10qIGIak1bKbYhKFQkV2wyCYELHKY='
} }
check.dependsOn('checkAPIChanges') check.dependsOn('checkAPIChanges')

@ -15,6 +15,7 @@
package org.hyperledger.besu.plugin.services; package org.hyperledger.besu.plugin.services;
import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest;
import org.hyperledger.besu.plugin.services.rpc.PluginRpcResponse;
import java.util.function.Function; import java.util.function.Function;
@ -54,4 +55,13 @@ public interface RpcEndpointService extends BesuService {
*/ */
<T> void registerRPCEndpoint( <T> void registerRPCEndpoint(
String namespace, String functionName, Function<PluginRpcRequest, T> function); String namespace, String functionName, Function<PluginRpcRequest, T> function);
/**
* Allow to call any of the enabled in-process RPC methods
*
* @param methodName the method to invoke
* @param params the list of parameters accepted by the method
* @return the result of the method
*/
PluginRpcResponse call(String methodName, Object[] params);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright ConsenSys AG. * Copyright contributors to Hyperledger Besu.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * 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 * the License. You may obtain a copy of the License at

@ -0,0 +1,27 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.rpc;
/** The interface Plugin rpc response. */
public interface PluginRpcResponse extends RpcResponse {
/**
* Get the result, unfortunately there is no typing yet, so call must know how to interact with
* the response
*
* @return the result
*/
Object getResult();
}

@ -0,0 +1,26 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.rpc;
/** Represent a Json RPC response */
public interface RpcResponse {
/**
* Get the response type
*
* @return the response type
*/
RpcResponseType getType();
}
Loading…
Cancel
Save