From 9fda9769e583ff9a52c961d9e9963d6d88b5d402 Mon Sep 17 00:00:00 2001 From: Jason Frame Date: Tue, 12 Oct 2021 14:24:49 +1000 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 75b4a419496ff3f82045484969f291c9f845aa6c Author: Jason Frame Date: Tue Oct 12 13:47:01 2021 +1000 add block header test case Signed-off-by: Jason Frame commit 7d3001dcbe9b677d428cda16710aa4d1a40c4da7 Author: Jason Frame Date: Tue Oct 12 13:31:08 2021 +1000 undo unintentional change fixing unit test Signed-off-by: Jason Frame commit 772a4281dcaeac1bfc6475b33e816b66684552d5 Author: Jason Frame Date: Tue Oct 12 13:21:56 2021 +1000 Qbft validation selection was incorrectly being applied for non validator selection mode transitions Signed-off-by: Jason Frame commit a30c31429058c836d675d24ed5a9fd95af988608 Author: Antony Denyer Date: Mon Oct 11 09:45:52 2021 +0100 Allow Besu to host RPC endpoints via a plugin. (#2754) This is a re-implementation of the initial POC done in https://github.com/PegaSysEng/pantheon/pull/1909/ by Danno Ferrin * Only enable plugin rpc api when enabled on --rpc-http-api or --rpc-ws-apis * Only allow new rpc endpoints to be defined Signed-off-by: Antony Denyer commit fc687ab1a49c5569a988486b9e9f67b3b2fc2fea Author: Simon Dudley Date: Mon Oct 11 08:18:03 2021 +0100 Qbft RPCs should be disabled after starting with or switching to use validator contract (#2817) Signed-off-by: Simon Dudley commit 93013e9324f1a262bd1ffb803ba4d7f5b333c2c2 Author: Usman Saleem Date: Fri Oct 8 15:51:40 2021 +1000 Add QBFT support for evmtool (#2807) * qbft support in evmtool Signed-off-by: Usman Saleem commit 215e18c90127166320f206b1481b69a48a9fb4d5 Author: Sally MacFarlane Date: Fri Oct 8 12:32:52 2021 +1000 master.svg -> main.svg (#2864) Signed-off-by: Sally MacFarlane commit 82ecef6c90d02a095b86ca42f4741a08eef54175 Author: Sally MacFarlane Date: Fri Oct 8 11:13:11 2021 +1000 Fixed build badge (#2863) * typos Signed-off-by: Sally MacFarlane * master -> main Signed-off-by: Sally MacFarlane commit 5fbf0b1605c9c1398a83b28ff10133f3a941ba5f Author: Sally MacFarlane Date: Thu Oct 7 19:22:47 2021 +1000 changed to trace level logging (#2858) Signed-off-by: Sally MacFarlane commit fdd935262b7fb7e11abdf895dde5a555f950e6b6 Author: Diego López León Date: Wed Oct 6 21:51:33 2021 -0300 Add a bash/zsh autocomplete script to distributions (#538) (#2854) Signed-off-by: Diego López León --- CHANGELOG.md | 3 +- README.md | 6 +- .../dsl/node/ProcessBesuNodeRunner.java | 6 +- .../dsl/node/ThreadBesuNodeRunner.java | 2 + .../BesuNodeConfigurationBuilder.java | 12 +- .../node/configuration/BesuNodeFactory.java | 5 +- .../NodeConfigurationFactory.java | 25 ++-- .../PermissionedNodeBuilder.java | 7 +- .../besu/plugins/TestPicoCLIPlugin.java | 3 +- .../plugins/TestRpcEndpointServicePlugin.java | 72 +++++++++ .../RpcApisTogglesAcceptanceTest.java | 2 +- .../plugins/RpcEndpointServicePluginTest.java | 122 +++++++++++++++ .../org/hyperledger/besu/RunnerBuilder.java | 34 ++++- .../org/hyperledger/besu/cli/BesuCommand.java | 65 +++++--- .../besu/cli/converter/RpcApisConverter.java | 42 ------ .../besu/controller/BesuController.java | 3 +- .../besu/services/RpcEndpointServiceImpl.java | 63 ++++++++ .../hyperledger/besu/RunnerBuilderTest.java | 3 + .../java/org/hyperledger/besu/RunnerTest.java | 5 +- .../hyperledger/besu/cli/BesuCommandTest.java | 29 +++- .../besu/cli/CommandTestAbstract.java | 8 +- build.gradle | 23 ++- .../besu/config/JsonGenesisConfigOptions.java | 3 + .../clique/jsonrpc/CliqueJsonRpcMethods.java | 6 +- .../clique/jsonrpc/CliqueRpcApis.java | 31 ---- .../bft/BaseBftProtocolScheduleTest.java | 2 - .../AbstractVoteProposerMethodTest.java | 17 +++ .../ibft/jsonrpc/IbftJsonRpcMethods.java | 6 +- .../consensus/qbft/QbftProtocolSchedule.java | 13 +- .../qbft/jsonrpc/QbftJsonRpcMethods.java | 6 +- .../consensus/qbft/jsonrpc/QbftRpcApis.java | 31 ---- .../methods/QbftDiscardValidatorVote.java | 2 +- .../methods/QbftProposeValidatorVote.java | 2 +- .../NoOpTransactionVoteProvider.java | 47 ------ .../TransactionValidatorProvider.java | 2 +- .../consensus/qbft/QbftBlockHeaderUtils.java | 112 ++++++++++++++ ...ockHeaderValidationRulesetFactoryTest.java | 120 +++++---------- .../qbft/QbftProtocolScheduleTest.java | 141 ++++++++++++++++++ .../methods/QbftDiscardValidatorVoteTest.java | 16 +- .../methods/QbftProposeValidatorVoteTest.java | 18 ++- .../TransactionValidatorProviderTest.java | 8 + .../jsonrpc/JsonRpcTestMethodsFactory.java | 12 +- .../api/jsonrpc/JsonRpcConfiguration.java | 12 +- .../besu/ethereum/api/jsonrpc/RpcApi.java | 51 ------- .../besu/ethereum/api/jsonrpc/RpcApis.java | 75 +++------- .../internal/methods/PluginJsonRpcMethod.java | 57 +++++++ .../jsonrpc/internal/methods/RpcModules.java | 4 +- .../jsonrpc/methods/AdminJsonRpcMethods.java | 5 +- .../methods/ApiGroupJsonRpcMethods.java | 5 +- .../jsonrpc/methods/DebugJsonRpcMethods.java | 5 +- .../jsonrpc/methods/EeaJsonRpcMethods.java | 5 +- .../jsonrpc/methods/EthJsonRpcMethods.java | 5 +- .../GoQuorumJsonRpcPrivacyMethods.java | 5 +- .../api/jsonrpc/methods/JsonRpcMethods.java | 3 +- .../methods/JsonRpcMethodsFactory.java | 3 +- .../jsonrpc/methods/MinerJsonRpcMethods.java | 5 +- .../jsonrpc/methods/NetJsonRpcMethods.java | 5 +- .../jsonrpc/methods/PermJsonRpcMethods.java | 5 +- .../methods/PluginsJsonRpcMethods.java | 5 +- .../jsonrpc/methods/PrivJsonRpcMethods.java | 5 +- .../jsonrpc/methods/PrivxJsonRpcMethods.java | 5 +- .../jsonrpc/methods/TraceJsonRpcMethods.java | 5 +- .../jsonrpc/methods/TxPoolJsonRpcMethods.java | 5 +- .../jsonrpc/methods/Web3JsonRpcMethods.java | 5 +- .../websocket/WebSocketConfiguration.java | 14 +- .../AbstractJsonRpcHttpServiceTest.java | 9 +- .../api/jsonrpc/JsonRpcConfigurationTest.java | 15 +- .../JsonRpcHttpServiceHostAllowlistTest.java | 7 +- .../jsonrpc/JsonRpcHttpServiceLoginTest.java | 5 +- .../JsonRpcHttpServiceRpcApisTest.java | 10 +- .../jsonrpc/JsonRpcHttpServiceTestBase.java | 5 +- .../JsonRpcHttpServiceTlsClientAuthTest.java | 10 +- ...RpcHttpServiceTlsMisconfigurationTest.java | 8 +- .../jsonrpc/JsonRpcHttpServiceTlsTest.java | 9 +- .../internal/methods/RpcModulesTest.java | 2 +- .../PrivacyApiGroupJsonRpcMethodsTest.java | 5 +- .../websocket/WebSocketConfigurationTest.java | 6 +- ethereum/evmtool/build.gradle | 1 + .../besu/evmtool/GenesisFileModule.java | 2 + .../besu/evmtool/QBFTGenesisFileModule.java | 45 ++++++ ...eSmartContractPermissioningController.java | 2 +- ...martContractV2PermissioningController.java | 4 +- .../besu/evm/worldstate/MutableWorldView.java | 2 +- plugin-api/build.gradle | 2 +- .../plugin/services/RpcEndpointService.java | 57 +++++++ .../plugin/services/rpc/PluginRpcRequest.java | 18 +-- 86 files changed, 1083 insertions(+), 570 deletions(-) create mode 100644 acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestRpcEndpointServicePlugin.java create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java delete mode 100644 besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java create mode 100644 besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java delete mode 100644 consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueRpcApis.java delete mode 100644 consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftRpcApis.java delete mode 100644 consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/NoOpTransactionVoteProvider.java create mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderUtils.java create mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java delete mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApi.java create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/PluginJsonRpcMethod.java create mode 100644 ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/RpcEndpointService.java rename consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftRpcApis.java => plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.java (59%) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc63923d719..bc6ee6fb56a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ ## 21.10.0-RC2 ### Additions and Improvements +- Add CLI autocomplete scripts. [#2854](https://github.com/hyperledger/besu/pull/2854) ### Bug Fixes ### Early Access Features - +- Enable plugins to expose custom JSON-RPC / WebSocket methods [#1317](https://github.com/hyperledger/besu/issues/1317) ## 21.10.0-RC1 ### Additions and Improvements diff --git a/README.md b/README.md index df4becd1ffe..e1922938c4c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Besu Ethereum Client - [![CircleCI](https://circleci.com/gh/hyperledger/besu/tree/master.svg?style=svg)](https://circleci.com/gh/hyperledger/besu/tree/master) + [![CircleCI](https://circleci.com/gh/hyperledger/besu/tree/main.svg?style=svg)](https://circleci.com/gh/hyperledger/besu/tree/main) [![Total alerts](https://img.shields.io/lgtm/alerts/g/hyperledger/besu.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/hyperledger/besu/alerts/) [![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/hyperledger/besu.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/hyperledger/besu/context:java) [![Documentation Status](https://readthedocs.org/projects/hyperledger-besu/badge/?version=latest)](https://besu.hyperledger.org/en/latest/?badge=latest) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3174/badge)](https://bestpractices.coreinfrastructure.org/projects/3174) - [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hyperledger/besu/blob/master/LICENSE) + [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hyperledger/besu/blob/main/LICENSE) [![RocketChat chat](https://open.rocket.chat/images/join-chat.svg)](https://chat.hyperledger.org/channel/besu) [Download](https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/) @@ -70,4 +70,4 @@ and YourKit YouMonitor. [Besu Issues]: https://github.com/hyperledger/besu/issues [Besu User Documentation]: https://besu.hyperledger.org [RocketChat]: https://chat.hyperledger.org/ -[Contributing Guidelines]: CONTRIBUTING.md \ No newline at end of file +[Contributing Guidelines]: CONTRIBUTING.md diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 3b919ef1ac0..7975571c45e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -18,8 +18,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -447,8 +445,8 @@ private void createStaticNodes(final BesuNode node) { StaticNodesUtils.createStaticNodesFile(node.homeDirectory(), node.getStaticNodes()); } - private String apiList(final Collection rpcApis) { - return rpcApis.stream().map(RpcApis::getValue).collect(Collectors.joining(",")); + private String apiList(final Collection rpcApis) { + return String.join(",", rpcApis); } @Override diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 1f668bcaeed..227591b405c 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -49,6 +49,7 @@ import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; @@ -211,6 +212,7 @@ public void startNode(final BesuNode node) { .autoLogBloomCaching(false) .storageProvider(storageProvider) .forkIdSupplier(() -> besuController.getProtocolManager().getForkIdAsBytesList()) + .rpcEndpointService(new RpcEndpointServiceImpl()) .build(); runner.start(); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java index d7650a89b66..85181ea1b33 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java @@ -107,13 +107,13 @@ public BesuNodeConfigurationBuilder miningEnabled() { public BesuNodeConfigurationBuilder miningEnabled(final boolean enabled) { this.miningParameters = new MiningParameters.Builder().enabled(enabled).coinbase(AddressHelpers.ofValue(1)).build(); - this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER); + this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name()); return this; } public BesuNodeConfigurationBuilder miningConfiguration(final MiningParameters miningParameters) { this.miningParameters = miningParameters; - this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER); + this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name()); return this; } @@ -143,18 +143,18 @@ public BesuNodeConfigurationBuilder metricsEnabled() { } public BesuNodeConfigurationBuilder enablePrivateTransactions() { - this.jsonRpcConfiguration.addRpcApi(RpcApis.EEA); - this.jsonRpcConfiguration.addRpcApi(RpcApis.PRIV); + this.jsonRpcConfiguration.addRpcApi(RpcApis.EEA.name()); + this.jsonRpcConfiguration.addRpcApi(RpcApis.PRIV.name()); return this; } public BesuNodeConfigurationBuilder jsonRpcTxPool() { - this.jsonRpcConfiguration.addRpcApi(RpcApis.TX_POOL); + this.jsonRpcConfiguration.addRpcApi(RpcApis.TXPOOL.name()); return this; } public BesuNodeConfigurationBuilder jsonRpcAdmin() { - this.jsonRpcConfiguration.addRpcApi(RpcApis.ADMIN); + this.jsonRpcConfiguration.addRpcApi(RpcApis.ADMIN.name()); return this; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index e5d5c88568c..95234f15c85 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -24,7 +24,6 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.enclave.EnclaveFactory; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.core.AddressHelpers; import org.hyperledger.besu.ethereum.core.InMemoryPrivacyStorageProvider; @@ -255,12 +254,14 @@ public BesuNode createPluginsNode( return create( new BesuNodeConfigurationBuilder() .name(name) + .jsonRpcConfiguration(node.createJsonRpcWithIbft2AdminEnabledConfig()) + .webSocketConfiguration(node.createWebSocketEnabledConfig()) .plugins(plugins) .extraCLIOptions(extraCLIOptions) .build()); } - public BesuNode createArchiveNodeWithRpcApis(final String name, final RpcApi... enabledRpcApis) + public BesuNode createArchiveNodeWithRpcApis(final String name, final String... enabledRpcApis) throws IOException { final JsonRpcConfiguration jsonRpcConfig = node.createJsonRpcEnabledConfig(); jsonRpcConfig.setRpcApis(asList(enabledRpcApis)); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java index 4d279513deb..f2682993f8a 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java @@ -16,14 +16,13 @@ import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; -import static org.hyperledger.besu.consensus.clique.jsonrpc.CliqueRpcApis.CLIQUE; -import static org.hyperledger.besu.consensus.ibft.jsonrpc.IbftRpcApis.IBFT; -import static org.hyperledger.besu.consensus.qbft.jsonrpc.QbftRpcApis.QBFT; import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ADMIN; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.CLIQUE; +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.QBFT; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; 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.configuration.genesis.GenesisConfigurationProvider; @@ -46,23 +45,23 @@ public Optional createGenesisConfigForValidators( } public JsonRpcConfiguration createJsonRpcWithCliqueEnabledConfig() { - return createJsonRpcWithRpcApiEnabledConfig(CLIQUE); + return createJsonRpcWithRpcApiEnabledConfig(CLIQUE.name()); } public JsonRpcConfiguration createJsonRpcWithIbft2EnabledConfig(final boolean minerEnabled) { return minerEnabled - ? createJsonRpcWithRpcApiEnabledConfig(IBFT, MINER) - : createJsonRpcWithRpcApiEnabledConfig(IBFT); + ? createJsonRpcWithRpcApiEnabledConfig(IBFT.name(), MINER.name()) + : createJsonRpcWithRpcApiEnabledConfig(IBFT.name()); } public JsonRpcConfiguration createJsonRpcWithIbft2AdminEnabledConfig() { - return createJsonRpcWithRpcApiEnabledConfig(IBFT, ADMIN); + return createJsonRpcWithRpcApiEnabledConfig(IBFT.name(), ADMIN.name()); } public JsonRpcConfiguration createJsonRpcWithQbftEnabledConfig(final boolean minerEnabled) { return minerEnabled - ? createJsonRpcWithRpcApiEnabledConfig(QBFT, MINER) - : createJsonRpcWithRpcApiEnabledConfig(QBFT); + ? createJsonRpcWithRpcApiEnabledConfig(QBFT.name(), MINER.name()) + : createJsonRpcWithRpcApiEnabledConfig(QBFT.name()); } public JsonRpcConfiguration createJsonRpcEnabledConfig() { @@ -81,12 +80,12 @@ public WebSocketConfiguration createWebSocketEnabledConfig() { } public JsonRpcConfiguration jsonRpcConfigWithAdmin() { - return createJsonRpcWithRpcApiEnabledConfig(ADMIN); + return createJsonRpcWithRpcApiEnabledConfig(ADMIN.name()); } - public JsonRpcConfiguration createJsonRpcWithRpcApiEnabledConfig(final RpcApi... rpcApi) { + public JsonRpcConfiguration createJsonRpcWithRpcApiEnabledConfig(final String... rpcApi) { final JsonRpcConfiguration jsonRpcConfig = createJsonRpcEnabledConfig(); - final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); + final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); rpcApis.addAll(Arrays.asList(rpcApi)); jsonRpcConfig.setRpcApis(rpcApis); return jsonRpcConfig; diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java index b84c57072ff..8dafc14d77f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.permissioning.AllowlistPersistor; @@ -297,9 +296,9 @@ private JsonRpcConfiguration jsonRpcConfigWithPermApiEnabled() { jsonRpcConfig.setPort(0); jsonRpcConfig.setHostsAllowlist(singletonList("*")); jsonRpcConfig.setCorsAllowedDomains(singletonList("*")); - final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); - rpcApis.add(RpcApis.PERM); - rpcApis.add(RpcApis.ADMIN); + final List rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis()); + rpcApis.add(RpcApis.PERM.name()); + rpcApis.add(RpcApis.ADMIN.name()); jsonRpcConfig.setRpcApis(rpcApis); return jsonRpcConfig; } diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java index 37192404dab..be82423a2de 100644 --- a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPicoCLIPlugin.java @@ -59,8 +59,7 @@ public void register(final BesuContext context) { context .getService(PicoCLIOptions.class) - .ifPresent( - picoCLIOptions -> picoCLIOptions.addPicoCLIOptions("test", TestPicoCLIPlugin.this)); + .ifPresent(picoCLIOptions -> picoCLIOptions.addPicoCLIOptions("test", this)); callbackDir = new File(System.getProperty("besu.plugins.dir", "plugins")); writeSignal("registered"); diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestRpcEndpointServicePlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestRpcEndpointServicePlugin.java new file mode 100644 index 00000000000..807d6ab077e --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestRpcEndpointServicePlugin.java @@ -0,0 +1,72 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.plugins; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.hyperledger.besu.plugin.BesuContext; +import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.services.RpcEndpointService; +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; + +import java.util.concurrent.atomic.AtomicReference; + +import com.google.auto.service.AutoService; + +@AutoService(BesuPlugin.class) +public class TestRpcEndpointServicePlugin implements BesuPlugin { + + private final AtomicReference stringStorage = new AtomicReference<>("InitialValue"); + private final AtomicReference arrayStorage = new AtomicReference<>(); + + private String setValue(final PluginRpcRequest request) { + checkArgument(request.getParams().length == 1, "Only one parameter accepted"); + return stringStorage.updateAndGet(x -> request.getParams()[0].toString()); + } + + private String getValue(final PluginRpcRequest request) { + return stringStorage.get(); + } + + private Object[] replaceValueList(final PluginRpcRequest request) { + return arrayStorage.updateAndGet(x -> request.getParams()); + } + + private String throwException(final PluginRpcRequest request) { + throw new RuntimeException("Kaboom"); + } + + @Override + public void register(final BesuContext context) { + context + .getService(RpcEndpointService.class) + .ifPresent( + rpcEndpointService -> { + rpcEndpointService.registerRPCEndpoint("tests", "getValue", this::getValue); + rpcEndpointService.registerRPCEndpoint("tests", "setValue", this::setValue); + rpcEndpointService.registerRPCEndpoint( + "tests", "replaceValueList", this::replaceValueList); + rpcEndpointService.registerRPCEndpoint( + "tests", "throwException", this::throwException); + rpcEndpointService.registerRPCEndpoint("notEnabled", "getValue", this::getValue); + }); + } + + @Override + public void start() {} + + @Override + public void stop() {} +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java index 6ffed6e8b9c..3eb9821f8ef 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/RpcApisTogglesAcceptanceTest.java @@ -35,7 +35,7 @@ public class RpcApisTogglesAcceptanceTest extends AcceptanceTestBase { public void before() throws Exception { rpcEnabledNode = besu.createArchiveNode("rpc-enabled"); rpcDisabledNode = besu.createArchiveNodeWithRpcDisabled("rpc-disabled"); - ethApiDisabledNode = besu.createArchiveNodeWithRpcApis("eth-api-disabled", RpcApis.NET); + ethApiDisabledNode = besu.createArchiveNodeWithRpcApis("eth-api-disabled", RpcApis.NET.name()); cluster.start(rpcEnabledNode, rpcDisabledNode, ethApiDisabledNode); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java new file mode 100644 index 00000000000..4463e434c0d --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/RpcEndpointServicePluginTest.java @@ -0,0 +1,122 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import org.junit.Before; +import org.junit.Test; + +public class RpcEndpointServicePluginTest extends AcceptanceTestBase { + + private BesuNode node; + + private OkHttpClient client; + protected static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + + @Before + public void setUp() throws Exception { + node = besu.createPluginsNode("node1", List.of("testPlugins"), List.of("--rpc-http-api=TESTS")); + cluster.start(node); + client = new OkHttpClient(); + } + + @Test + public void canUseRpcToSetValue() throws IOException { + String setValue = "secondCall"; + + ObjectNode resultJson = callTestMethod("tests_getValue", List.of()); + assertThat(resultJson.get("result").asText()).isEqualTo("InitialValue"); + + resultJson = callTestMethod("tests_setValue", List.of(setValue)); + assertThat(resultJson.get("result").asText()).isEqualTo(setValue); + + resultJson = callTestMethod("tests_getValue", List.of("ignored")); + assertThat(resultJson.get("result").asText()).isEqualTo(setValue); + } + + @Test + public void canCheckArgumentInsideSetValue() throws IOException { + ObjectNode resultJson = callTestMethod("tests_setValue", List.of("one", "two")); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Internal error"); + } + + @Test + public void exceptionsInPluginMethodReturnError() throws IOException { + ObjectNode resultJson = callTestMethod("tests_throwException", List.of()); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Internal error"); + } + + @Test + public void onlyEnabledMethodsReturn() throws IOException { + ObjectNode resultJson = callTestMethod("notEnabled_getValue", List.of()); + assertThat(resultJson.get("error").get("message").asText()).isEqualTo("Method not found"); + } + + @Test + public void mixedTypeArraysAreStringified() throws IOException { + ObjectNode resultJson = callTestMethod("tests_replaceValueList", List.of()); + assertThat(resultJson.get("result")).isEmpty(); + + resultJson = callTestMethod("tests_replaceValueList", List.of("One", 2, true)); + JsonNode result = resultJson.get("result"); + + assertThat(result.get(0).asText()).isEqualTo("One"); + assertThat(result.get(1).asText()).isEqualTo("2"); + assertThat(result.get(2).asText()).isEqualTo("true"); + } + + private ObjectNode callTestMethod(final String method, final List params) + throws IOException { + String format = + String.format( + "{\"jsonrpc\":\"2.0\",\"method\":\"%s\",\"params\":[%s],\"id\":42}", + method, + params.stream().map(value -> "\"" + value + "\"").collect(Collectors.joining(","))); + + RequestBody body = RequestBody.create(format, JSON); + + final String resultString = + client + .newCall( + new Request.Builder() + .post(body) + .url( + "http://" + + node.getHostName() + + ":" + + node.getJsonRpcSocketPort().get() + + "/") + .build()) + .execute() + .body() + .string(); + return JsonUtil.objectNodeFromString(resultString); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 4122643a1a3..ee69acf9be9 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -33,7 +33,6 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLProvider; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.health.HealthService; import org.hyperledger.besu.ethereum.api.jsonrpc.health.LivenessCheck; import org.hyperledger.besu.ethereum.api.jsonrpc.health.ReadinessCheck; @@ -109,6 +108,7 @@ import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.PermissioningServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.util.NetworkUtility; import java.io.IOException; @@ -175,6 +175,7 @@ public class RunnerBuilder { private boolean randomPeerPriority; private StorageProvider storageProvider; private Supplier> forkIdSupplier; + private RpcEndpointServiceImpl rpcEndpointServiceImpl; public RunnerBuilder vertx(final Vertx vertx) { this.vertx = vertx; @@ -368,6 +369,11 @@ public RunnerBuilder forkIdSupplier(final Supplier> forkIdSupplier) return this; } + public RunnerBuilder rpcEndpointService(final RpcEndpointServiceImpl rpcEndpointService) { + this.rpcEndpointServiceImpl = rpcEndpointService; + return this; + } + public Runner build() { Preconditions.checkNotNull(besuController); @@ -567,7 +573,8 @@ public Runner build() { metricsConfiguration, natService, besuPluginContext.getNamedPlugins(), - dataDir); + dataDir, + rpcEndpointServiceImpl); jsonRpcHttpService = Optional.of( new JsonRpcHttpService( @@ -634,7 +641,8 @@ public Runner build() { metricsConfiguration, natService, besuPluginContext.getNamedPlugins(), - dataDir); + dataDir, + rpcEndpointServiceImpl); final SubscriptionManager subscriptionManager = createSubscriptionManager(vertx, transactionPool, blockchainQueries); @@ -816,7 +824,7 @@ private Map jsonRpcMethods( final MiningCoordinator miningCoordinator, final ObservableMetricsSystem metricsSystem, final Set supportedCapabilities, - final Collection jsonRpcApis, + final Collection jsonRpcApis, final FilterManager filterManager, final Optional accountAllowlistController, final Optional nodeAllowlistController, @@ -826,7 +834,8 @@ private Map jsonRpcMethods( final MetricsConfiguration metricsConfiguration, final NatService natService, final Map namedPlugins, - final Path dataDir) { + final Path dataDir, + final RpcEndpointServiceImpl rpcEndpointServiceImpl) { final Map methods = new JsonRpcMethodsFactory() .methods( @@ -854,6 +863,16 @@ private Map jsonRpcMethods( dataDir, besuController.getProtocolManager().ethContext().getEthPeers()); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); + + var pluginMethods = rpcEndpointServiceImpl.getPluginMethods(jsonRpcConfiguration.getRpcApis()); + + var overriddenMethods = + methods.keySet().stream().filter(pluginMethods::containsKey).collect(Collectors.toList()); + if (overriddenMethods.size() > 0) { + throw new RuntimeException("You can not override built in methods " + overriddenMethods); + } + + methods.putAll(pluginMethods); return methods; } @@ -955,6 +974,11 @@ private WebSocketService createWebsocketService( privateWebSocketMethodsFactory.methods().forEach(websocketMethodsFactory::addMethods); } + rpcEndpointServiceImpl + .getPluginMethods(configuration.getRpcApis()) + .values() + .forEach(websocketMethodsFactory::addMethods); + final WebSocketRequestHandler websocketRequestHandler = new WebSocketRequestHandler( vertx, diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 0890f5a8ca7..d5c7ab02513 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -24,7 +24,7 @@ import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEFAULT_GRAPHQL_HTTP_PORT; import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_JSON_RPC_PORT; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_JSON_RPC_APIS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; 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; @@ -43,7 +43,6 @@ import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.converter.PercentageConverter; -import org.hyperledger.besu.cli.converter.RpcApisConverter; import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty; import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty; import org.hyperledger.besu.cli.custom.RpcAuthFileValidator; @@ -101,7 +100,6 @@ import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; @@ -152,6 +150,7 @@ import org.hyperledger.besu.plugin.services.PermissioningService; import org.hyperledger.besu.plugin.services.PicoCLIOptions; import org.hyperledger.besu.plugin.services.PrivacyPluginService; +import org.hyperledger.besu.plugin.services.RpcEndpointService; import org.hyperledger.besu.plugin.services.SecurityModuleService; import org.hyperledger.besu.plugin.services.StorageService; import org.hyperledger.besu.plugin.services.exception.StorageException; @@ -165,6 +164,7 @@ import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl; import org.hyperledger.besu.services.PrivacyPluginServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin; @@ -185,6 +185,7 @@ import java.nio.file.Path; import java.time.Clock; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.Collection; import java.util.HashMap; @@ -197,6 +198,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -220,6 +222,7 @@ import org.apache.logging.log4j.core.config.Configurator; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; +import picocli.AutoComplete; import picocli.CommandLine; import picocli.CommandLine.AbstractParseResultHandler; import picocli.CommandLine.Command; @@ -281,6 +284,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { private final SecurityModuleServiceImpl securityModuleService; private final PermissioningServiceImpl permissioningService; private final PrivacyPluginServiceImpl privacyPluginPluginService; + private final RpcEndpointServiceImpl rpcEndpointServiceImpl; private final Map environment; private final MetricCategoryRegistryImpl metricCategoryRegistry = @@ -548,12 +552,11 @@ void setBannedNodeIds(final List values) { @Option( names = {"--rpc-http-api", "--rpc-http-apis"}, paramLabel = "", - split = ",", + split = " {0,1}, {0,1}", arity = "1..*", - converter = RpcApisConverter.class, description = "Comma separated list of APIs to enable on JSON-RPC HTTP service (default: ${DEFAULT-VALUE})") - private final Collection rpcHttpApis = DEFAULT_JSON_RPC_APIS; + private final List rpcHttpApis = DEFAULT_RPC_APIS; @Option( names = {"--rpc-http-authentication-enabled"}, @@ -645,12 +648,11 @@ void setBannedNodeIds(final List values) { @Option( names = {"--rpc-ws-api", "--rpc-ws-apis"}, paramLabel = "", - split = ",", + split = " {0,1}, {0,1}", arity = "1..*", - converter = RpcApisConverter.class, description = "Comma separated list of APIs to enable on JSON-RPC WebSocket service (default: ${DEFAULT-VALUE})") - private final List rpcWsApis = DEFAULT_JSON_RPC_APIS; + private final List rpcWsApis = DEFAULT_RPC_APIS; @Option( names = {"--rpc-ws-authentication-enabled"}, @@ -1140,7 +1142,8 @@ public BesuCommand( new SecurityModuleServiceImpl(), new PermissioningServiceImpl(), new PrivacyPluginServiceImpl(), - new PkiBlockCreationConfigurationProvider()); + new PkiBlockCreationConfigurationProvider(), + new RpcEndpointServiceImpl()); } @VisibleForTesting @@ -1157,7 +1160,8 @@ protected BesuCommand( final SecurityModuleServiceImpl securityModuleService, final PermissioningServiceImpl permissioningService, final PrivacyPluginServiceImpl privacyPluginPluginService, - final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider) { + final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider, + final RpcEndpointServiceImpl rpcEndpointServiceImpl) { this.logger = logger; this.rlpBlockImporter = rlpBlockImporter; this.rlpBlockExporterFactory = rlpBlockExporterFactory; @@ -1173,6 +1177,7 @@ protected BesuCommand( pluginCommonConfiguration = new BesuCommandConfigurationService(); besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration); this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider; + this.rpcEndpointServiceImpl = rpcEndpointServiceImpl; } public void parse( @@ -1250,6 +1255,12 @@ private void addSubCommands( RLPSubCommand.COMMAND_NAME, new RLPSubCommand(resultHandler.out(), in)); commandLine.addSubcommand( OperatorSubCommand.COMMAND_NAME, new OperatorSubCommand(resultHandler.out())); + final String generateCompletionSubcommandName = "generate-completion"; + commandLine.addSubcommand( + generateCompletionSubcommandName, AutoComplete.GenerateCompletion.class); + CommandLine generateCompletionSubcommand = + commandLine.getSubcommands().get(generateCompletionSubcommandName); + generateCompletionSubcommand.getCommandSpec().usageMessage().hidden(true); } private void registerConverters() { @@ -1306,6 +1317,7 @@ private void preparePlugins() { besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry); besuPluginContext.addService(PermissioningService.class, permissioningService); besuPluginContext.addService(PrivacyPluginService.class, privacyPluginPluginService); + besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); // register built-in plugins new RocksDBPlugin().register(besuPluginContext); @@ -1446,6 +1458,7 @@ private void validateOptions() { validateNatParams(); validateNetStatsParams(); validateDnsOptionsParams(); + validateRpcOptionsParams(); p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine); pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine); } @@ -1515,6 +1528,22 @@ private void validateDnsOptionsParams() { } } + public void validateRpcOptionsParams() { + Predicate configuredApis = + apiName -> + Arrays.stream(RpcApis.values()) + .anyMatch(builtInApi -> apiName.equals(builtInApi.name())) + || rpcEndpointServiceImpl.hasNamespace(apiName); + + if (!rpcHttpApis.stream().allMatch(configuredApis)) { + throw new ParameterException(this.commandLine, "Invalid value for option '--rpc-http-apis'"); + } + + if (!rpcWsApis.stream().allMatch(configuredApis)) { + throw new ParameterException(this.commandLine, "Invalid value for option '--rpc-ws-apis'"); + } + } + private GenesisConfigOptions readGenesisConfigOptions() { final GenesisConfigOptions genesisConfigOptions; try { @@ -1986,7 +2015,7 @@ public MetricsConfiguration metricsConfiguration() { private Optional permissioningConfiguration() throws Exception { if (!(localPermissionsEnabled() || contractPermissionsEnabled())) { - if (rpcHttpApis.contains(RpcApis.PERM) || rpcWsApis.contains(RpcApis.PERM)) { + if (rpcHttpApis.contains(RpcApis.PERM.name()) || rpcWsApis.contains(RpcApis.PERM.name())) { logger.warn( "Permissions are disabled. Cannot enable PERM APIs when not using Permissions."); } @@ -2218,7 +2247,8 @@ private PrivacyParameters privacyParameters(final KeyValueStorageProvider storag } if (!isGoQuorumCompatibilityMode - && (rpcHttpApis.contains(RpcApis.GOQUORUM) || rpcWsApis.contains(RpcApis.GOQUORUM))) { + && (rpcHttpApis.contains(RpcApis.GOQUORUM.name()) + || rpcWsApis.contains(RpcApis.GOQUORUM.name()))) { logger.warn("Cannot use GOQUORUM API methods when not in GoQuorum mode."); } privacyParametersBuilder.setPrivacyService(privacyPluginPluginService); @@ -2241,10 +2271,10 @@ public WorldStateArchive createPrivateWorldStateArchive(final StorageProvider st } private boolean anyPrivacyApiEnabled() { - return rpcHttpApis.contains(RpcApis.EEA) - || rpcWsApis.contains(RpcApis.EEA) - || rpcHttpApis.contains(RpcApis.PRIV) - || rpcWsApis.contains(RpcApis.PRIV); + return rpcHttpApis.contains(RpcApis.EEA.name()) + || rpcWsApis.contains(RpcApis.EEA.name()) + || rpcHttpApis.contains(RpcApis.PRIV.name()) + || rpcWsApis.contains(RpcApis.PRIV.name()); } private PrivacyKeyValueStorageProvider privacyKeyStorageProvider(final String name) { @@ -2374,6 +2404,7 @@ private void synchronize( .ethstatsContact(ethstatsOptions.getEthstatsContact()) .storageProvider(keyValueStorageProvider(keyValueStorageName)) .forkIdSupplier(() -> besuController.getProtocolManager().getForkIdAsBytesList()) + .rpcEndpointService(rpcEndpointServiceImpl) .build(); addShutdownHook(runner); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java deleted file mode 100644 index ec6960e72c7..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/RpcApisConverter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 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. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.converter; - -import org.hyperledger.besu.cli.converter.exception.RpcApisConversionException; -import org.hyperledger.besu.consensus.clique.jsonrpc.CliqueRpcApis; -import org.hyperledger.besu.consensus.ibft.jsonrpc.IbftRpcApis; -import org.hyperledger.besu.consensus.qbft.jsonrpc.QbftRpcApis; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; - -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Stream; - -import picocli.CommandLine; - -public class RpcApisConverter implements CommandLine.ITypeConverter { - - @Override - public RpcApi convert(final String name) throws RpcApisConversionException { - return Stream.>>of( - RpcApis::valueOf, CliqueRpcApis::valueOf, IbftRpcApis::valueOf, QbftRpcApis::valueOf) - .map(f -> f.apply(name.trim().toUpperCase())) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst() - .orElseThrow(() -> new RpcApisConversionException(name)); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java index db4c31f9ab0..cdee3b7b703 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java @@ -20,7 +20,6 @@ import org.hyperledger.besu.config.PowAlgorithm; import org.hyperledger.besu.crypto.NodeKey; import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; @@ -156,7 +155,7 @@ public MiningParameters getMiningParameters() { } public Map getAdditionalJsonRpcMethods( - final Collection enabledRpcApis) { + final Collection enabledRpcApis) { return additionalJsonRpcMethodsFactory.create(enabledRpcApis); } diff --git a/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java new file mode 100644 index 00000000000..fc21d8bbff1 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java @@ -0,0 +1,63 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.services; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginJsonRpcMethod; +import org.hyperledger.besu.plugin.services.RpcEndpointService; +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class RpcEndpointServiceImpl implements RpcEndpointService { + private final Map> rpcMethods = new HashMap<>(); + + @Override + public void registerRPCEndpoint( + final String namespace, + final String functionName, + final Function function) { + checkArgument(namespace.matches("\\p{Alnum}+"), "Namespace must be only alpha numeric"); + checkArgument(functionName.matches("\\p{Alnum}+"), "Function Name must be only alpha numeric"); + checkNotNull(function); + + rpcMethods.put(namespace + "_" + functionName, function); + } + + public Map getPluginMethods( + final Collection namespaces) { + return rpcMethods.entrySet().stream() + .filter( + entry -> + namespaces.stream() + .anyMatch( + namespace -> + entry.getKey().toUpperCase().startsWith(namespace.toUpperCase()))) + .map(entry -> new PluginJsonRpcMethod(entry.getKey(), entry.getValue())) + .collect(Collectors.toMap(PluginJsonRpcMethod::getName, e -> e)); + } + + public boolean hasNamespace(final String namespace) { + return rpcMethods.keySet().stream() + .anyMatch(key -> key.toUpperCase().startsWith(namespace.toUpperCase())); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java index f8568878855..58c52866e0e 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java @@ -57,6 +57,7 @@ import org.hyperledger.besu.nat.NatMethod; import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.services.PermissioningServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -142,6 +143,7 @@ public void enodeUrlShouldHaveAdvertisedHostWhenDiscoveryDisabled() { .dataDir(dataDir.getRoot().toPath()) .storageProvider(mock(KeyValueStorageProvider.class)) .forkIdSupplier(() -> Collections.singletonList(Bytes.EMPTY)) + .rpcEndpointService(new RpcEndpointServiceImpl()) .build(); runner.start(); @@ -185,6 +187,7 @@ public void movingAcrossProtocolSpecsUpdatesNodeRecord() { .dataDir(dataDir.getRoot().toPath()) .storageProvider(storageProvider) .forkIdSupplier(() -> Collections.singletonList(Bytes.EMPTY)) + .rpcEndpointService(new RpcEndpointServiceImpl()) .build(); runner.start(); when(besuController.getProtocolSchedule().streamMilestoneBlocks()) diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 8da04d5322c..6eeb918d60e 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -60,6 +60,7 @@ import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.PermissioningServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.testutil.TestClock; import java.math.BigInteger; @@ -211,7 +212,8 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .permissioningService(new PermissioningServiceImpl()) .staticNodes(emptySet()) .storageProvider(new InMemoryKeyValueStorageProvider()) - .forkIdSupplier(() -> Collections.singletonList(Bytes.EMPTY)); + .forkIdSupplier(() -> Collections.singletonList(Bytes.EMPTY)) + .rpcEndpointService(new RpcEndpointServiceImpl()); Runner runnerBehind = null; final Runner runnerAhead = @@ -226,6 +228,7 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .pidPath(pidPath) .besuPluginContext(new BesuPluginContextImpl()) .forkIdSupplier(() -> controllerAhead.getProtocolManager().getForkIdAsBytesList()) + .rpcEndpointService(new RpcEndpointServiceImpl()) .build(); try { diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index b40f5e33327..773ee9d30f6 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -57,7 +57,6 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.handlers.TimeoutOptions; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; import org.hyperledger.besu.ethereum.core.MiningParameters; @@ -76,6 +75,7 @@ import org.hyperledger.besu.nat.NatMethod; import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; import org.hyperledger.besu.plugin.data.EnodeURL; +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; import org.hyperledger.besu.util.number.Fraction; import org.hyperledger.besu.util.number.Percentage; @@ -93,6 +93,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -315,7 +316,7 @@ public void overrideDefaultValuesIfKeyIsPresentInConfigFile() throws IOException final Path toml = createTempFile("toml", updatedConfig.getBytes(UTF_8)); - final List expectedApis = asList(ETH, WEB3); + final List expectedApis = asList(ETH.name(), WEB3.name()); final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); jsonRpcConfiguration.setEnabled(false); @@ -1823,7 +1824,7 @@ public void rpcApisPropertyMustBeUsed() { .warn("Permissions are disabled. Cannot enable PERM APIs when not using Permissions."); assertThat(jsonRpcConfigArgumentCaptor.getValue().getRpcApis()) - .containsExactlyInAnyOrder(ETH, NET, PERM); + .containsExactlyInAnyOrder(ETH.name(), NET.name(), PERM.name()); assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); @@ -1837,7 +1838,7 @@ public void rpcApisPropertyIgnoresDuplicatesAndMustBeUsed() { verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getRpcApis()) - .containsExactlyInAnyOrder(ETH, NET); + .containsExactlyInAnyOrder(ETH.name(), NET.name()); assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); @@ -1927,6 +1928,24 @@ public void rpcApisPropertyWithInvalidEntryMustDisplayError() { .contains("Invalid value for option '--rpc-http-apis'"); } + @Test + public void rpcApisPropertyWithPluginNamespaceAreValid() { + + rpcEndpointServiceImpl.registerRPCEndpoint( + "bob", "method", (Function) request -> "nothing"); + + parseCommand("--rpc-http-api", "BOB"); + + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); + + assertThat(jsonRpcConfigArgumentCaptor.getValue().getRpcApis()) + .containsExactlyInAnyOrder("BOB"); + + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + } + @Test public void rpcHttpHostAndPortOptionsMustBeUsed() { @@ -2682,7 +2701,7 @@ public void rpcWsApiPropertyMustBeUsed() { verify(mockRunnerBuilder).build(); assertThat(wsRpcConfigArgumentCaptor.getValue().getRpcApis()) - .containsExactlyInAnyOrder(ETH, NET); + .containsExactlyInAnyOrder(ETH.name(), NET.name()); assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index 056aa5278a9..7c3b296d2c3 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -75,6 +75,7 @@ import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PrivacyPluginServiceImpl; +import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; @@ -133,6 +134,9 @@ public abstract class CommandTestAbstract { private final List besuCommands = new ArrayList<>(); private KeyPair keyPair; + protected static final RpcEndpointServiceImpl rpcEndpointServiceImpl = + new RpcEndpointServiceImpl(); + @Mock protected RunnerBuilder mockRunnerBuilder; @Mock protected Runner mockRunner; @@ -275,6 +279,7 @@ public void initMocks() throws Exception { when(mockRunnerBuilder.ethstatsContact(anyString())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.storageProvider(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.forkIdSupplier(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.rpcEndpointService(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.build()).thenReturn(mockRunner); final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance(); @@ -409,7 +414,8 @@ public static class TestBesuCommand extends BesuCommand { securityModuleService, new PermissioningServiceImpl(), new PrivacyPluginServiceImpl(), - pkiBlockCreationConfigProvider); + pkiBlockCreationConfigProvider, + rpcEndpointServiceImpl); } @Override diff --git a/build.gradle b/build.gradle index fc9e6e75126..daaec85f5d8 100644 --- a/build.gradle +++ b/build.gradle @@ -524,10 +524,28 @@ task evmToolStartScripts(type: CreateStartScripts) { } } +task autocomplete(type: JavaExec) { + dependsOn compileJava + def tempAutocompleteFile = File.createTempFile("besu", ".autocomplete") + standardOutput tempAutocompleteFile.newOutputStream() + outputs.file "$buildDir/besu.autocomplete.sh" + + mainClass = application.mainClass + args "generate-completion" + classpath sourceSets.main.runtimeClasspath + doLast { + copy { + from tempAutocompleteFile + into "$buildDir" + rename tempAutocompleteFile.getName(), 'besu.autocomplete.sh' + } + } +} + installDist { dependsOn checkLicenses } distTar { - dependsOn checkLicenses + dependsOn checkLicenses, autocomplete doFirst { delete fileTree(dir: 'build/distributions', include: '*.tar.gz') } @@ -536,7 +554,7 @@ distTar { } distZip { - dependsOn checkLicenses + dependsOn checkLicenses, autocomplete doFirst { delete fileTree(dir: 'build/distributions', include: '*.zip') } @@ -863,6 +881,7 @@ distributions { from("build/reports/license/license-dependency.html") { into "." } from("./docs/GettingStartedBinaries.md") { into "." } from("./docs/DocsArchive0.8.0.html") { into "." } + from("build/besu.autocomplete.sh") { into "." } } } } diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 0e600d7c9db..1e3dc940bf6 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -439,6 +439,9 @@ public Map asMap() { if (isIbft2()) { builder.put("ibft2", getBftConfigOptions().asMap()); } + if (isQbft()) { + builder.put("qbft", getQbftConfigOptions().asMap()); + } if (isQuorum()) { builder.put("isQuorum", true); diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java index ddf63811d44..67617736db7 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java @@ -26,7 +26,7 @@ import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider; import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; @@ -43,8 +43,8 @@ public CliqueJsonRpcMethods(final ProtocolContext context) { } @Override - protected RpcApi getApiGroup() { - return CliqueRpcApis.CLIQUE; + protected String getApiGroup() { + return RpcApis.CLIQUE.name(); } @Override diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueRpcApis.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueRpcApis.java deleted file mode 100644 index e9b58bf9331..00000000000 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueRpcApis.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 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. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.consensus.clique.jsonrpc; - -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; - -import java.util.Optional; - -public class CliqueRpcApis { - public static final RpcApi CLIQUE = new RpcApi("CLIQUE"); - - public static final Optional valueOf(final String name) { - if (name.equals(CLIQUE.getCliValue())) { - return Optional.of(CLIQUE); - } else { - return Optional.empty(); - } - } -} diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleTest.java index 08868f86a5f..f8ddc737987 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleTest.java @@ -61,8 +61,6 @@ public void ensureBlockRewardAndMiningBeneficiaryInProtocolSpecMatchConfig() { final ProtocolSchedule schedule = createProtocolSchedule(); final ProtocolSpec spec = schedule.getByBlockNumber(1); - spec.getBlockReward(); - assertThat(spec.getBlockReward()).isEqualTo(Wei.of(arbitraryBlockReward)); assertThat(spec.getMiningBeneficiaryCalculator().calculateBeneficiary(null)) .isEqualTo(Address.fromHexString(miningBeneficiary)); diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/jsonrpc/AbstractVoteProposerMethodTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/jsonrpc/AbstractVoteProposerMethodTest.java index 23406ae3065..3e9dd745ef4 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/jsonrpc/AbstractVoteProposerMethodTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/jsonrpc/AbstractVoteProposerMethodTest.java @@ -24,12 +24,15 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import java.util.Optional; import com.google.common.collect.ImmutableMap; +import org.assertj.core.api.Assertions; import org.junit.Test; public abstract class AbstractVoteProposerMethodTest { @@ -74,4 +77,18 @@ public void testConversionFromVoteTypeToBoolean() { assertThat(response).isEqualToComparingFieldByField(expectedResponse); } + + @Test + public void methodNotEnabledWhenNoVoteProvider() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest(JSON_RPC_VERSION, getMethodName(), new Object[] {})); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.METHOD_NOT_ENABLED); + when(validatorProvider.getVoteProvider()).thenReturn(Optional.empty()); + + final JsonRpcResponse response = getMethod().response(request); + + Assertions.assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); + } } diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java index e223b3ac320..df037db9d31 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java @@ -27,7 +27,7 @@ import org.hyperledger.besu.consensus.ibft.jsonrpc.methods.IbftGetValidatorsByBlockNumber; import org.hyperledger.besu.consensus.ibft.jsonrpc.methods.IbftProposeValidatorVote; import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; @@ -44,8 +44,8 @@ public IbftJsonRpcMethods(final ProtocolContext context) { } @Override - protected RpcApi getApiGroup() { - return IbftRpcApis.IBFT; + protected String getApiGroup() { + return RpcApis.IBFT.name(); } @Override diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftProtocolSchedule.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftProtocolSchedule.java index 9ab714e8090..11400862367 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftProtocolSchedule.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftProtocolSchedule.java @@ -50,12 +50,23 @@ public static ProtocolSchedule create( return create(config, PrivacyParameters.DEFAULT, false, bftExtraDataCodec, evmConfiguration); } + public static ProtocolSchedule create( + final GenesisConfigOptions config, + final boolean isRevertReasonEnabled, + final BftExtraDataCodec bftExtraDataCodec) { + return create( + config, + PrivacyParameters.DEFAULT, + isRevertReasonEnabled, + bftExtraDataCodec, + EvmConfiguration.DEFAULT); + } + @Override protected Supplier createForkBlockHeaderRuleset( final GenesisConfigOptions config, final BftFork fork) { checkArgument(fork instanceof QbftFork, "QbftProtocolSchedule must use QbftForks"); final QbftFork qbftFork = (QbftFork) fork; - // TODO add test case for transition without validation selection return () -> QbftBlockHeaderValidationRulesetFactory.blockHeaderValidator( fork.getBlockPeriodSeconds() diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftJsonRpcMethods.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftJsonRpcMethods.java index 3c56d851238..383ceec28e8 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftJsonRpcMethods.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftJsonRpcMethods.java @@ -27,7 +27,7 @@ import org.hyperledger.besu.consensus.qbft.jsonrpc.methods.QbftGetValidatorsByBlockNumber; import org.hyperledger.besu.consensus.qbft.jsonrpc.methods.QbftProposeValidatorVote; import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; @@ -44,8 +44,8 @@ public QbftJsonRpcMethods(final ProtocolContext context) { } @Override - protected RpcApi getApiGroup() { - return QbftRpcApis.QBFT; + protected String getApiGroup() { + return RpcApis.QBFT.name(); } @Override diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftRpcApis.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftRpcApis.java deleted file mode 100644 index 1be27777a09..00000000000 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftRpcApis.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 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. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.consensus.qbft.jsonrpc; - -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; - -import java.util.Optional; - -public class QbftRpcApis { - public static final RpcApi QBFT = new RpcApi("QBFT"); - - public static final Optional valueOf(final String name) { - if (name.equals(QBFT.getCliValue())) { - return Optional.of(QBFT); - } else { - return Optional.empty(); - } - } -} diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVote.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVote.java index f712793d78d..21c8d019a8f 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVote.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVote.java @@ -50,7 +50,7 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), true); } else { return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), JsonRpcError.METHOD_UNIMPLEMENTED); + requestContext.getRequest().getId(), JsonRpcError.METHOD_NOT_ENABLED); } } } diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVote.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVote.java index 9303019f660..74dbbaaf770 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVote.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVote.java @@ -60,7 +60,7 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), true); } else { return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), JsonRpcError.METHOD_UNIMPLEMENTED); + requestContext.getRequest().getId(), JsonRpcError.METHOD_NOT_ENABLED); } } } diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/NoOpTransactionVoteProvider.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/NoOpTransactionVoteProvider.java deleted file mode 100644 index 8eb5435a464..00000000000 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/NoOpTransactionVoteProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.hyperledger.besu.consensus.qbft.validator; -/* - * Copyright 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. - * - * SPDX-License-Identifier: Apache-2.0 - */ -import org.hyperledger.besu.consensus.common.validator.ValidatorVote; -import org.hyperledger.besu.consensus.common.validator.VoteProvider; -import org.hyperledger.besu.consensus.common.validator.VoteType; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.ethereum.core.BlockHeader; - -import java.util.Collections; -import java.util.Map; -import java.util.Optional; - -public class NoOpTransactionVoteProvider implements VoteProvider { - - @Override - public Optional getVoteAfterBlock( - final BlockHeader header, final Address localAddress) { - return Optional.empty(); - } - - @Override - public void authVote(final Address address) {} - - @Override - public void dropVote(final Address address) {} - - @Override - public void discardVote(final Address address) {} - - @Override - public Map getProposals() { - return Collections.emptyMap(); - } -} diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProvider.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProvider.java index 934953fe187..305d01d7e51 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProvider.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProvider.java @@ -69,6 +69,6 @@ public Collection
getValidatorsForBlock(final BlockHeader header) { @Override public Optional getVoteProvider() { - return Optional.of(new NoOpTransactionVoteProvider()); + return Optional.empty(); } } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderUtils.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderUtils.java new file mode 100644 index 00000000000..97985d03c43 --- /dev/null +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderUtils.java @@ -0,0 +1,112 @@ +package org.hyperledger.besu.consensus.qbft; + +import static java.util.Collections.singletonList; + +import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; +import org.hyperledger.besu.consensus.common.bft.BftExtraData; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataFixture; +import org.hyperledger.besu.consensus.common.bft.Vote; +import org.hyperledger.besu.crypto.NodeKey; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.Util; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; + +public class QbftBlockHeaderUtils { + + @FunctionalInterface + public interface HeaderModifier { + + void update(BlockHeaderTestFixture blockHeaderTestFixture); + } + + public static BlockHeaderTestFixture createPresetHeaderBuilder( + final long number, + final NodeKey proposerNodeKey, + final List
validators, + final BlockHeader parent) { + return createPresetHeaderBuilder(number, proposerNodeKey, validators, parent, null); + } + + public static BlockHeaderTestFixture createPresetHeaderBuilderForContractMode( + final long number, + final NodeKey proposerNodeKey, + final BlockHeader parent, + final HeaderModifier modifier) { + final BlockHeaderTestFixture builder = new BlockHeaderTestFixture(); + final QbftExtraDataCodec qbftExtraDataEncoder = new QbftExtraDataCodec(); + populateDefaultBlockHeader( + number, proposerNodeKey, parent, modifier, builder, qbftExtraDataEncoder); + + final BftExtraData bftExtraData = + BftExtraDataFixture.createExtraData( + builder.buildHeader(), + Bytes.wrap(new byte[BftExtraDataCodec.EXTRA_VANITY_LENGTH]), + Optional.empty(), + Collections.emptyList(), + singletonList(proposerNodeKey), + 0x2A, + qbftExtraDataEncoder); + + builder.extraData(qbftExtraDataEncoder.encode(bftExtraData)); + return builder; + } + + public static BlockHeaderTestFixture createPresetHeaderBuilder( + final long number, + final NodeKey proposerNodeKey, + final List
validators, + final BlockHeader parent, + final HeaderModifier modifier) { + final BlockHeaderTestFixture builder = new BlockHeaderTestFixture(); + final QbftExtraDataCodec qbftExtraDataEncoder = new QbftExtraDataCodec(); + populateDefaultBlockHeader( + number, proposerNodeKey, parent, modifier, builder, qbftExtraDataEncoder); + + final BftExtraData bftExtraData = + BftExtraDataFixture.createExtraData( + builder.buildHeader(), + Bytes.wrap(new byte[BftExtraDataCodec.EXTRA_VANITY_LENGTH]), + Optional.of(Vote.authVote(Address.fromHexString("1"))), + validators, + singletonList(proposerNodeKey), + 0x2A, + qbftExtraDataEncoder); + + builder.extraData(qbftExtraDataEncoder.encode(bftExtraData)); + return builder; + } + + private static void populateDefaultBlockHeader( + final long number, + final NodeKey proposerNodeKey, + final BlockHeader parent, + final HeaderModifier modifier, + final BlockHeaderTestFixture builder, + final QbftExtraDataCodec qbftExtraDataEncoder) { + if (parent != null) { + builder.parentHash(parent.getHash()); + } + builder.number(number); + builder.gasLimit(5000); + builder.timestamp(6000 * number); + builder.mixHash( + Hash.fromHexString("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365")); + builder.difficulty(Difficulty.ONE); + builder.coinbase(Util.publicKeyToAddress(proposerNodeKey.getPublicKey())); + builder.blockHeaderFunctions(BftBlockHeaderFunctions.forCommittedSeal(qbftExtraDataEncoder)); + + if (modifier != null) { + modifier.update(builder); + } + } +} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java index 176acf96991..d6cc389ccb6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java @@ -19,18 +19,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; -import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; -import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; -import org.hyperledger.besu.consensus.common.bft.BftExtraDataFixture; -import org.hyperledger.besu.consensus.common.bft.Vote; import org.hyperledger.besu.crypto.NodeKey; import org.hyperledger.besu.crypto.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; @@ -38,9 +32,7 @@ import java.util.Collection; import java.util.List; -import java.util.Optional; -import org.apache.tuweni.bytes.Bytes; import org.junit.Test; public class QbftBlockHeaderValidationRulesetFactoryTest { @@ -61,9 +53,11 @@ public void bftValidateHeaderPasses() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + .buildHeader(); final BlockHeaderValidator validator = QbftBlockHeaderValidationRulesetFactory.blockHeaderValidator(5, false).build(); @@ -82,9 +76,12 @@ public void bftValidateHeaderFailsWhenExtraDataDoesntContainValidatorList() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, emptyList(), parentHeader).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder( + 2, proposerNodeKey, emptyList(), parentHeader) + .buildHeader(); final BlockHeaderValidator validator = QbftBlockHeaderValidationRulesetFactory.blockHeaderValidator(5, false).build(); @@ -106,9 +103,10 @@ public void bftValidateHeaderFailsOnCoinbaseData() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) .coinbase(nonProposerAddress) .buildHeader(); @@ -129,9 +127,10 @@ public void bftValidateHeaderIgnoresNonceValue() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder( + QbftBlockHeaderUtils.createPresetHeaderBuilder( 2, proposerNodeKey, validators, parentHeader, builder -> builder.nonce(3)) .buildHeader(); @@ -152,9 +151,10 @@ public void bftValidateHeaderFailsOnTimestamp() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) .timestamp(100) .buildHeader(); @@ -175,9 +175,10 @@ public void bftValidateHeaderFailsOnMixHash() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder( + QbftBlockHeaderUtils.createPresetHeaderBuilder( 2, proposerNodeKey, validators, @@ -202,9 +203,10 @@ public void bftValidateHeaderIgnoresOmmersValue() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder( + QbftBlockHeaderUtils.createPresetHeaderBuilder( 2, proposerNodeKey, validators, @@ -229,9 +231,10 @@ public void bftValidateHeaderFailsOnDifficulty() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) .difficulty(Difficulty.of(5)) .buildHeader(); @@ -252,9 +255,11 @@ public void bftValidateHeaderFailsOnAncestor() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeaderValidator validator = QbftBlockHeaderValidationRulesetFactory.blockHeaderValidator(5, false).build(); @@ -273,9 +278,10 @@ public void bftValidateHeaderFailsOnGasUsage() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) .gasLimit(5_000) .gasUsed(6_000) .buildHeader(); @@ -297,9 +303,10 @@ public void bftValidateHeaderFailsOnGasLimitRange() { final List
validators = singletonList(proposerAddress); final BlockHeader parentHeader = - getPresetHeaderBuilder(1, proposerNodeKey, validators, null).buildHeader(); + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); final BlockHeader blockHeader = - getPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) .gasLimit(4999) .buildHeader(); @@ -311,57 +318,4 @@ public void bftValidateHeaderFailsOnGasLimitRange() { blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.FULL)) .isFalse(); } - - private BlockHeaderTestFixture getPresetHeaderBuilder( - final long number, - final NodeKey proposerNodeKey, - final List
validators, - final BlockHeader parent) { - return getPresetHeaderBuilder(number, proposerNodeKey, validators, parent, null); - } - - private BlockHeaderTestFixture getPresetHeaderBuilder( - final long number, - final NodeKey proposerNodeKey, - final List
validators, - final BlockHeader parent, - final HeaderModifier modifier) { - final BlockHeaderTestFixture builder = new BlockHeaderTestFixture(); - final QbftExtraDataCodec qbftExtraDataEncoder = new QbftExtraDataCodec(); - - if (parent != null) { - builder.parentHash(parent.getHash()); - } - builder.number(number); - builder.gasLimit(5000); - builder.timestamp(6000 * number); - builder.mixHash( - Hash.fromHexString("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365")); - builder.difficulty(Difficulty.ONE); - builder.coinbase(Util.publicKeyToAddress(proposerNodeKey.getPublicKey())); - builder.blockHeaderFunctions(BftBlockHeaderFunctions.forCommittedSeal(qbftExtraDataEncoder)); - - if (modifier != null) { - modifier.update(builder); - } - - final BftExtraData bftExtraData = - BftExtraDataFixture.createExtraData( - builder.buildHeader(), - Bytes.wrap(new byte[BftExtraDataCodec.EXTRA_VANITY_LENGTH]), - Optional.of(Vote.authVote(Address.fromHexString("1"))), - validators, - singletonList(proposerNodeKey), - 0x2A, - qbftExtraDataEncoder); - - builder.extraData(qbftExtraDataEncoder.encode(bftExtraData)); - return builder; - } - - @FunctionalInterface - public interface HeaderModifier { - - void update(BlockHeaderTestFixture blockHeaderTestFixture); - } } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java new file mode 100644 index 00000000000..0c92cd3bad9 --- /dev/null +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java @@ -0,0 +1,141 @@ +package org.hyperledger.besu.consensus.qbft; + +import static java.util.Collections.singletonList; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.config.QbftConfigOptions; +import org.hyperledger.besu.config.QbftFork; +import org.hyperledger.besu.config.QbftFork.VALIDATOR_SELECTION_MODE; +import org.hyperledger.besu.config.StubGenesisConfigOptions; +import org.hyperledger.besu.config.TransitionsConfigOptions; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; +import org.hyperledger.besu.crypto.NodeKey; +import org.hyperledger.besu.crypto.NodeKeyUtils; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; +import org.hyperledger.besu.ethereum.core.Util; +import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.evm.internal.EvmConfiguration; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +public class QbftProtocolScheduleTest { + private final BftExtraDataCodec bftExtraDataCodec = mock(BftExtraDataCodec.class); + private final TransitionsConfigOptions transitionsConfigOptions = + mock(TransitionsConfigOptions.class); + private final NodeKey proposerNodeKey = NodeKeyUtils.generate(); + private final Address proposerAddress = Util.publicKeyToAddress(proposerNodeKey.getPublicKey()); + private final List
validators = singletonList(proposerAddress); + + private ProtocolContext protocolContext(final Collection
validators) { + return new ProtocolContext( + null, + null, + setupContextWithBftExtraDataEncoder( + QbftContext.class, validators, new QbftExtraDataCodec())); + } + + @Test + public void contractModeTransitionsCreatesContractModeHeaderValidators() { + final QbftFork arbitraryFork = + new QbftFork( + JsonUtil.objectNodeFromMap( + Map.of(QbftFork.FORK_BLOCK_KEY, 1, QbftFork.BLOCK_REWARD_KEY, "1"))); + final QbftFork contractModeFork = + new QbftFork( + JsonUtil.objectNodeFromMap( + Map.of( + QbftFork.FORK_BLOCK_KEY, + 2, + QbftFork.VALIDATOR_SELECTION_MODE_KEY, + VALIDATOR_SELECTION_MODE.CONTRACT, + QbftFork.VALIDATOR_CONTRACT_ADDRESS_KEY, + "0x1"))); + final QbftConfigOptions qbftConfigOptions = + new QbftConfigOptions( + JsonUtil.objectNodeFromMap(Map.of(QbftFork.VALIDATOR_CONTRACT_ADDRESS_KEY, "0x1"))); + final BlockHeader parentHeader = + QbftBlockHeaderUtils.createPresetHeaderBuilderForContractMode( + 1, proposerNodeKey, null, null) + .buildHeader(); + final BlockHeader blockHeader = + QbftBlockHeaderUtils.createPresetHeaderBuilderForContractMode( + 2, proposerNodeKey, parentHeader, null) + .buildHeader(); + + final ProtocolSchedule schedule = + createProtocolSchedule(List.of(arbitraryFork, contractModeFork), qbftConfigOptions); + assertThat(schedule.streamMilestoneBlocks().count()).isEqualTo(3); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 0)).isTrue(); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 1)).isTrue(); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 2)).isTrue(); + } + + @Test + public void blockModeTransitionsCreatesBlockModeHeaderValidators() { + final QbftFork arbitraryFork = + new QbftFork( + JsonUtil.objectNodeFromMap( + Map.of(QbftFork.FORK_BLOCK_KEY, 1, QbftFork.BLOCK_REWARD_KEY, "1"))); + final QbftFork blockModeFork = + new QbftFork( + JsonUtil.objectNodeFromMap( + Map.of( + QbftFork.FORK_BLOCK_KEY, + 2, + QbftFork.VALIDATOR_SELECTION_MODE_KEY, + VALIDATOR_SELECTION_MODE.BLOCKHEADER))); + final BlockHeader parentHeader = + QbftBlockHeaderUtils.createPresetHeaderBuilder(1, proposerNodeKey, validators, null) + .buildHeader(); + final BlockHeader blockHeader = + QbftBlockHeaderUtils.createPresetHeaderBuilder(2, proposerNodeKey, validators, parentHeader) + .buildHeader(); + + final ProtocolSchedule schedule = + createProtocolSchedule(List.of(arbitraryFork, blockModeFork), QbftConfigOptions.DEFAULT); + assertThat(schedule.streamMilestoneBlocks().count()).isEqualTo(3); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 0)).isTrue(); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 1)).isTrue(); + assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 2)).isTrue(); + } + + private ProtocolSchedule createProtocolSchedule( + final List forks, final QbftConfigOptions qbftConfigOptions) { + final StubGenesisConfigOptions genesisConfig = new StubGenesisConfigOptions(); + genesisConfig.transitions(transitionsConfigOptions); + genesisConfig.qbftConfigOptions(qbftConfigOptions); + when(transitionsConfigOptions.getQbftForks()).thenReturn(forks); + + return QbftProtocolSchedule.create( + genesisConfig, + PrivacyParameters.DEFAULT, + false, + bftExtraDataCodec, + EvmConfiguration.DEFAULT); + } + + private boolean validateHeader( + final ProtocolSchedule schedule, + final List
validators, + final BlockHeader parentHeader, + final BlockHeader blockHeader, + final int block) { + return schedule + .getByBlockNumber(block) + .getBlockHeaderValidator() + .validateHeader( + blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT); + } +} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java index d15c2a7453e..a29fb3eeb54 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftDiscardValidatorVoteTest.java @@ -25,6 +25,8 @@ 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.exception.InvalidJsonRpcParameters; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; @@ -75,6 +77,18 @@ public void exceptionWhenInvalidAddressParameterSupplied() { method.response(request); } + @Test + public void methodNotEnabledWhenNoVoteProvider() { + final JsonRpcRequestContext request = requestWithParams(Address.fromHexString("1")); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.METHOD_NOT_ENABLED); + when(validatorProvider.getVoteProvider()).thenReturn(Optional.empty()); + + final JsonRpcResponse response = method.response(request); + + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); + } + @Test public void discardValidator() { final Address parameterAddress = Address.fromHexString("1"); @@ -85,7 +99,7 @@ public void discardValidator() { final JsonRpcResponse response = method.response(request); - assertThat(response).isEqualToComparingFieldByField(expectedResponse); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); verify(voteProvider).discardVote(parameterAddress); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java index 018207c874a..550baff4c32 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/jsonrpc/methods/QbftProposeValidatorVoteTest.java @@ -25,6 +25,8 @@ 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.exception.InvalidJsonRpcParameters; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; @@ -95,6 +97,18 @@ public void exceptionWhenInvalidBoolParameterSupplied() { method.response(request); } + @Test + public void methodNotEnabledWhenNoVoteProvider() { + final JsonRpcRequestContext request = requestWithParams(Address.fromHexString("1")); + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.METHOD_NOT_ENABLED); + when(validatorProvider.getVoteProvider()).thenReturn(Optional.empty()); + + final JsonRpcResponse response = method.response(request); + + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); + } + @Test public void addValidator() { final Address parameterAddress = Address.fromHexString("1"); @@ -104,7 +118,7 @@ public void addValidator() { final JsonRpcResponse response = method.response(request); - assertThat(response).isEqualToComparingFieldByField(expectedResponse); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); verify(voteProvider).authVote(parameterAddress); } @@ -118,7 +132,7 @@ public void removeValidator() { final JsonRpcResponse response = method.response(request); - assertThat(response).isEqualToComparingFieldByField(expectedResponse); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); verify(voteProvider).dropVote(parameterAddress); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java index cddaeeafab5..b9870185db6 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/TransactionValidatorProviderTest.java @@ -172,4 +172,12 @@ public void validatorsMustBeSorted() { validators.stream().sorted().collect(Collectors.toList()); assertThat(result).containsExactlyElementsOf(expectedValidators); } + + @Test + public void voteProviderIsEmpty() { + TransactionValidatorProvider transactionValidatorProvider = + new TransactionValidatorProvider(blockChain, validatorContractController); + + assertThat(transactionValidatorProvider.getVoteProvider()).isEmpty(); + } } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index e66d5ef9156..98e13a116aa 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -146,12 +146,12 @@ public Map methods() { final MetricsConfiguration metricsConfiguration = mock(MetricsConfiguration.class); final NatService natService = new NatService(Optional.empty()); - final List apis = new ArrayList<>(); - apis.add(RpcApis.ETH); - apis.add(RpcApis.NET); - apis.add(RpcApis.WEB3); - apis.add(RpcApis.PRIV); - apis.add(RpcApis.DEBUG); + final List apis = new ArrayList<>(); + apis.add(RpcApis.ETH.name()); + apis.add(RpcApis.NET.name()); + apis.add(RpcApis.WEB3.name()); + apis.add(RpcApis.PRIV.name()); + apis.add(RpcApis.DEBUG.name()); final Path dataDir = mock(Path.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfiguration.java index aa4a7df80bb..03a093dab41 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfiguration.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; + import org.hyperledger.besu.ethereum.api.handlers.TimeoutOptions; import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration; @@ -37,7 +39,7 @@ public class JsonRpcConfiguration { private int port; private String host; private List corsAllowedDomains = Collections.emptyList(); - private List rpcApis; + private List rpcApis; private List hostsAllowlist = Arrays.asList("localhost", "127.0.0.1"); private boolean authenticationEnabled = false; private String authenticationCredentialsFile; @@ -51,7 +53,7 @@ public static JsonRpcConfiguration createDefault() { config.setEnabled(false); config.setPort(DEFAULT_JSON_RPC_PORT); config.setHost(DEFAULT_JSON_RPC_HOST); - config.rpcApis = RpcApis.DEFAULT_JSON_RPC_APIS; + config.setRpcApis(DEFAULT_RPC_APIS); config.httpTimeoutSec = TimeoutOptions.defaultOptions().getTimeoutSeconds(); config.setMaxActiveConnections(DEFAULT_MAX_ACTIVE_CONNECTIONS); return config; @@ -93,15 +95,15 @@ public void setCorsAllowedDomains(final List corsAllowedDomains) { } } - public Collection getRpcApis() { + public Collection getRpcApis() { return rpcApis; } - public void setRpcApis(final List rpcApis) { + public void setRpcApis(final List rpcApis) { this.rpcApis = rpcApis; } - public void addRpcApi(final RpcApi rpcApi) { + public void addRpcApi(final String rpcApi) { this.rpcApis = new ArrayList<>(rpcApis); rpcApis.add(rpcApi); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApi.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApi.java deleted file mode 100644 index 476c6c138bf..00000000000 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApi.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 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. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.api.jsonrpc; - -import java.util.Objects; - -public class RpcApi { - private final String cliValue; - - public RpcApi(final String cliValue) { - this.cliValue = cliValue; - } - - public String getCliValue() { - return cliValue; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final RpcApi rpcApi = (RpcApi) o; - return Objects.equals(cliValue, rpcApi.cliValue); - } - - @Override - public int hashCode() { - return Objects.hashCode(cliValue); - } - - @Override - public String toString() { - return cliValue; - } -} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java index 953e04d5336..f98703ea2e2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java @@ -16,63 +16,24 @@ import java.util.Arrays; import java.util.List; -import java.util.Optional; -public class RpcApis { +public enum RpcApis { + ETH, + DEBUG, + MINER, + NET, + PERM, + WEB3, + ADMIN, + EEA, + PRIV, + TXPOOL, + TRACE, + PLUGINS, + GOQUORUM, + CLIQUE, + IBFT, + QBFT; - public static final RpcApi ETH = new RpcApi("ETH"); - public static final RpcApi DEBUG = new RpcApi("DEBUG"); - public static final RpcApi MINER = new RpcApi("MINER"); - public static final RpcApi NET = new RpcApi("NET"); - public static final RpcApi PERM = new RpcApi("PERM"); - public static final RpcApi WEB3 = new RpcApi("WEB3"); - public static final RpcApi ADMIN = new RpcApi("ADMIN"); - public static final RpcApi EEA = new RpcApi("EEA"); - public static final RpcApi PRIV = new RpcApi("PRIV"); - public static final RpcApi TX_POOL = new RpcApi("TXPOOL"); - public static final RpcApi TRACE = new RpcApi("TRACE"); - public static final RpcApi PLUGINS = new RpcApi("PLUGINS"); - public static final RpcApi GOQUORUM = new RpcApi("GOQUORUM"); - - public static final List DEFAULT_JSON_RPC_APIS = Arrays.asList(ETH, NET, WEB3); - - @SuppressWarnings("unused") - public static final List ALL_JSON_RPC_APIS = - Arrays.asList(ETH, DEBUG, MINER, NET, PERM, WEB3, ADMIN, EEA, PRIV, TX_POOL, TRACE, PLUGINS); - - public static Optional valueOf(final String name) { - if (name.equals(ETH.getCliValue())) { - return Optional.of(ETH); - } else if (name.equals(DEBUG.getCliValue())) { - return Optional.of(DEBUG); - } else if (name.equals(MINER.getCliValue())) { - return Optional.of(MINER); - } else if (name.equals(NET.getCliValue())) { - return Optional.of(NET); - } else if (name.equals(PERM.getCliValue())) { - return Optional.of(PERM); - } else if (name.equals(WEB3.getCliValue())) { - return Optional.of(WEB3); - } else if (name.equals(ADMIN.getCliValue())) { - return Optional.of(ADMIN); - } else if (name.equals(EEA.getCliValue())) { - return Optional.of(EEA); - } else if (name.equals(PRIV.getCliValue())) { - return Optional.of(PRIV); - } else if (name.equals(TX_POOL.getCliValue())) { - return Optional.of(TX_POOL); - } else if (name.equals(TRACE.getCliValue())) { - return Optional.of(TRACE); - } else if (name.equals(PLUGINS.getCliValue())) { - return Optional.of(PLUGINS); - } else if (name.equals(GOQUORUM.getCliValue())) { - return Optional.of(GOQUORUM); - } else { - return Optional.empty(); - } - } - - public static String getValue(final RpcApi rpcapi) { - return rpcapi.getCliValue(); - } + public static final List DEFAULT_RPC_APIS = Arrays.asList("ETH", "NET", "WEB3"); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/PluginJsonRpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/PluginJsonRpcMethod.java new file mode 100644 index 00000000000..9e3a61d728b --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/PluginJsonRpcMethod.java @@ -0,0 +1,57 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.INTERNAL_ERROR; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; + +import java.util.function.Function; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class PluginJsonRpcMethod implements JsonRpcMethod { + + private static final Logger LOG = LogManager.getLogger(); + + private final String name; + private final Function function; + + public PluginJsonRpcMethod(final String name, final Function function) { + this.name = name; + this.function = function; + } + + @Override + public String getName() { + return name; + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext request) { + try { + Object result = function.apply(() -> request.getRequest().getParams()); + return new JsonRpcSuccessResponse(request.getRequest().getId(), result); + } catch (Exception ex) { + LOG.error("Error calling plugin JSON-RPC endpoint", ex); + return new JsonRpcErrorResponse(request.getRequest().getId(), INTERNAL_ERROR); + } + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModules.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModules.java index c177fbe5c29..fc145d719fa 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModules.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModules.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; @@ -29,10 +28,9 @@ public class RpcModules implements JsonRpcMethod { private final Map moduleVersions; - public RpcModules(final Collection modulesList) { + public RpcModules(final Collection modulesList) { this.moduleVersions = modulesList.stream() - .map(RpcApi::getCliValue) .map(String::toLowerCase) .collect(Collectors.toMap(Function.identity(), s -> "1.0")); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java index 369c322c7e5..61109f73c84 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.config.GenesisConfigOptions; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.AdminAddPeer; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.AdminChangeLogLevel; @@ -67,8 +66,8 @@ public AdminJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.ADMIN; + protected String getApiGroup() { + return RpcApis.ADMIN.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ApiGroupJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ApiGroupJsonRpcMethods.java index eb1d04e17c3..e92df9fb527 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ApiGroupJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/ApiGroupJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import java.util.Arrays; @@ -26,11 +25,11 @@ public abstract class ApiGroupJsonRpcMethods implements JsonRpcMethods { @Override - public Map create(final Collection apis) { + public Map create(final Collection apis) { return apis.contains(getApiGroup()) ? create() : Collections.emptyMap(); } - protected abstract RpcApi getApiGroup(); + protected abstract String getApiGroup(); protected abstract Map create(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java index 7bac0f87634..014a2c7d2f0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugAccountAt; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugAccountRange; @@ -66,8 +65,8 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { } @Override - protected RpcApi getApiGroup() { - return RpcApis.DEBUG; + protected String getApiGroup() { + return RpcApis.DEBUG.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java index 31fc7e791e3..ae69302b219 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.ethereum.api.jsonrpc.LatestNonceProvider; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider; @@ -89,7 +88,7 @@ protected Map create( } @Override - protected RpcApi getApiGroup() { - return RpcApis.EEA; + protected String getApiGroup() { + return RpcApis.EEA.name(); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java index ffba7c3a40a..e1e8fb47bd7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManager; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthAccounts; @@ -108,8 +107,8 @@ public EthJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.ETH; + protected String getApiGroup() { + return RpcApis.ETH.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/GoQuorumJsonRpcPrivacyMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/GoQuorumJsonRpcPrivacyMethods.java index ec9f1011689..56b23f29a01 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/GoQuorumJsonRpcPrivacyMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/GoQuorumJsonRpcPrivacyMethods.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.enclave.GoQuorumEnclave; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider; @@ -66,7 +65,7 @@ enclave, getTransactionPool(), enclavePublicKeyProvider), } @Override - protected RpcApi getApiGroup() { - return RpcApis.GOQUORUM; + protected String getApiGroup() { + return RpcApis.GOQUORUM.name(); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethods.java index 0b4ae464772..697243fce0e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethods.java @@ -14,12 +14,11 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import java.util.Collection; import java.util.Map; public interface JsonRpcMethods { - Map create(Collection enabledRpcApis); + Map create(Collection enabledRpcApis); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index dec061e26df..0a09d34cfe0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -16,7 +16,6 @@ import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManager; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.RpcModules; @@ -63,7 +62,7 @@ public Map methods( final Set supportedCapabilities, final Optional accountsAllowlistController, final Optional nodeAllowlistController, - final Collection rpcApis, + final Collection rpcApis, final PrivacyParameters privacyParameters, final JsonRpcConfiguration jsonRpcConfiguration, final WebSocketConfiguration webSocketConfiguration, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/MinerJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/MinerJsonRpcMethods.java index 9530b9fe4c5..35d6502ad3f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/MinerJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/MinerJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerChangeTargetGasLimit; @@ -35,8 +34,8 @@ public MinerJsonRpcMethods(final MiningCoordinator miningCoordinator) { } @Override - protected RpcApi getApiGroup() { - return RpcApis.MINER; + protected String getApiGroup() { + return RpcApis.MINER.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/NetJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/NetJsonRpcMethods.java index 6ba51d6dc72..a3fcc318cf7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/NetJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/NetJsonRpcMethods.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.NetEnode; @@ -53,8 +52,8 @@ public NetJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.NET; + protected String getApiGroup() { + return RpcApis.NET.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PermJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PermJsonRpcMethods.java index 81b604c3ca4..3a3b6cfb003 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PermJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PermJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.permissioning.PermAddAccountsToAllowlist; @@ -49,8 +48,8 @@ public PermJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.PERM; + protected String getApiGroup() { + return RpcApis.PERM.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PluginsJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PluginsJsonRpcMethods.java index 2588566a70a..0b73b8f401c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PluginsJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PluginsJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginsReloadConfiguration; @@ -31,8 +30,8 @@ public PluginsJsonRpcMethods(final Map namedPlugins) { } @Override - protected RpcApi getApiGroup() { - return RpcApis.PLUGINS; + protected String getApiGroup() { + return RpcApis.PLUGINS.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java index 35e42de23f2..d079b0cad15 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManager; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; @@ -59,8 +58,8 @@ public PrivJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.PRIV; + protected String getApiGroup() { + return RpcApis.PRIV.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivxJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivxJsonRpcMethods.java index e0e75148020..3d2643ebb48 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivxJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivxJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider; @@ -39,8 +38,8 @@ public PrivxJsonRpcMethods( } @Override - protected RpcApi getApiGroup() { - return RpcApis.PRIV; + protected String getApiGroup() { + return RpcApis.PRIV.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java index a42fe7c0e14..b6e9f09d9b1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TraceBlock; @@ -39,9 +38,9 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods { } @Override - protected RpcApi getApiGroup() { + protected String getApiGroup() { // Disable TRACE functionality while under development - return RpcApis.TRACE; + return RpcApis.TRACE.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TxPoolJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TxPoolJsonRpcMethods.java index 63356484d5a..cc20c06b02b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TxPoolJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TxPoolJsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TxPoolBesuPendingTransactions; @@ -33,8 +32,8 @@ public TxPoolJsonRpcMethods(final TransactionPool transactionPool) { } @Override - protected RpcApi getApiGroup() { - return RpcApis.TX_POOL; + protected String getApiGroup() { + return RpcApis.TXPOOL.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/Web3JsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/Web3JsonRpcMethods.java index ca9176aec21..e89f27191f7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/Web3JsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/Web3JsonRpcMethods.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Web3ClientVersion; @@ -31,8 +30,8 @@ public Web3JsonRpcMethods(final String clientVersion) { } @Override - protected RpcApi getApiGroup() { - return RpcApis.WEB3; + protected String getApiGroup() { + return RpcApis.WEB3.name(); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java index 915462edfe5..9c9f43c8f8f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java @@ -14,9 +14,9 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.websocket; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; + import org.hyperledger.besu.ethereum.api.handlers.TimeoutOptions; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import java.io.File; import java.util.Arrays; @@ -30,14 +30,12 @@ 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 List DEFAULT_WEBSOCKET_APIS = - Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); public static final int DEFAULT_MAX_ACTIVE_CONNECTIONS = 80; private boolean enabled; private int port; private String host; - private List rpcApis; + private List rpcApis; private boolean authenticationEnabled = false; private String authenticationCredentialsFile; private List hostsAllowlist = Arrays.asList("localhost", "127.0.0.1"); @@ -50,7 +48,7 @@ public static WebSocketConfiguration createDefault() { config.setEnabled(false); config.setHost(DEFAULT_WEBSOCKET_HOST); config.setPort(DEFAULT_WEBSOCKET_PORT); - config.setRpcApis(DEFAULT_WEBSOCKET_APIS); + config.setRpcApis(DEFAULT_RPC_APIS); config.setTimeoutSec(TimeoutOptions.defaultOptions().getTimeoutSeconds()); config.setMaxActiveConnections(DEFAULT_MAX_ACTIVE_CONNECTIONS); return config; @@ -82,11 +80,11 @@ public int getPort() { return port; } - public Collection getRpcApis() { + public Collection getRpcApis() { return rpcApis; } - public void setRpcApis(final List rpcApis) { + public void setRpcApis(final List rpcApis) { this.rpcApis = rpcApis; } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java index 8ecc46f7ca0..730d99e3bbf 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java @@ -74,8 +74,13 @@ public abstract class AbstractJsonRpcHttpServiceTest { protected static String CLIENT_VERSION = "TestClientVersion/0.1.0"; protected static final BigInteger NETWORK_ID = BigInteger.valueOf(123); - protected static final Collection JSON_RPC_APIS = - Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3, RpcApis.DEBUG, RpcApis.TRACE); + protected static final Collection JSON_RPC_APIS = + Arrays.asList( + RpcApis.ETH.name(), + RpcApis.NET.name(), + RpcApis.WEB3.name(), + RpcApis.DEBUG.name(), + RpcApis.TRACE.name()); protected final Vertx vertx = Vertx.vertx(); protected JsonRpcHttpService service; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfigurationTest.java index 5a3abec2ff9..2caba2995d4 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcConfigurationTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import java.util.Optional; @@ -31,8 +32,7 @@ public void defaultConfiguration() { assertThat(configuration.getHost()).isEqualTo("127.0.0.1"); assertThat(configuration.getPort()).isEqualTo(8545); assertThat(configuration.getCorsAllowedDomains()).isEmpty(); - assertThat(configuration.getRpcApis()) - .containsExactlyInAnyOrder(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); + assertThat(configuration.getRpcApis()).containsExactlyInAnyOrderElementsOf(DEFAULT_RPC_APIS); assertThat(configuration.getMaxActiveConnections()) .isEqualTo(JsonRpcConfiguration.DEFAULT_MAX_ACTIVE_CONNECTIONS); } @@ -46,7 +46,7 @@ public void corsAllowedOriginsDefaultShouldBeEmptyList() { @Test public void rpcApiDefaultShouldBePredefinedList() { final JsonRpcConfiguration configuration = JsonRpcConfiguration.createDefault(); - assertThat(configuration.getRpcApis()).containsExactly(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); + assertThat(configuration.getRpcApis()).containsExactlyElementsOf(DEFAULT_RPC_APIS); } @Test @@ -64,11 +64,12 @@ public void settingCorsAllowedOriginsShouldOverridePreviousValues() { public void settingRpcApisShouldOverridePreviousValues() { final JsonRpcConfiguration configuration = JsonRpcConfiguration.createDefault(); - configuration.setRpcApis(Lists.newArrayList(RpcApis.ETH, RpcApis.MINER)); - assertThat(configuration.getRpcApis()).containsExactly(RpcApis.ETH, RpcApis.MINER); + configuration.setRpcApis(Lists.newArrayList(RpcApis.ETH.name(), RpcApis.MINER.name())); + assertThat(configuration.getRpcApis()) + .containsExactly(RpcApis.ETH.name(), RpcApis.MINER.name()); - configuration.setRpcApis(Lists.newArrayList(RpcApis.DEBUG)); - assertThat(configuration.getRpcApis()).containsExactly(RpcApis.DEBUG); + configuration.setRpcApis(Lists.newArrayList(RpcApis.DEBUG.name())); + assertThat(configuration.getRpcApis()).containsExactly(RpcApis.DEBUG.name()); } @Test diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java index 9ce4346615b..8ab74ede31a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -43,7 +44,6 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -77,8 +77,7 @@ public class JsonRpcHttpServiceHostAllowlistTest { private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; private static final BigInteger CHAIN_ID = BigInteger.valueOf(123); - private static final Collection JSON_RPC_APIS = - Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); + private final JsonRpcConfiguration jsonRpcConfig = createJsonRpcConfig(); private final NatService natService = new NatService(Optional.empty()); @@ -113,7 +112,7 @@ public void initServerAndClient() throws Exception { supportedCapabilities, Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(NodeLocalConfigPermissioningController.class)), - JSON_RPC_APIS, + DEFAULT_RPC_APIS, mock(PrivacyParameters.class), mock(JsonRpcConfiguration.class), mock(WebSocketConfiguration.class), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java index 4af7172a850..58d89182eb5 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -101,8 +101,9 @@ public class JsonRpcHttpServiceLoginTest { protected static P2PNetwork peerDiscoveryMock; protected static BlockchainQueries blockchainQueries; protected static Synchronizer synchronizer; - protected static final Collection JSON_RPC_APIS = - Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3, RpcApis.ADMIN); + protected static final Collection JSON_RPC_APIS = + Arrays.asList( + RpcApis.ETH.name(), RpcApis.NET.name(), RpcApis.WEB3.name(), RpcApis.ADMIN.name()); protected static JWTAuth jwtAuth; protected static String authPermissionsConfigFilePath = "JsonRpcHttpService/auth.toml"; protected final JsonRpcTestHelper testHelper = new JsonRpcTestHelper(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index d7c9f069833..ead1bd64fd2 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -125,7 +125,7 @@ public void requestWithNetMethodShouldSucceedWhenDefaultApisEnabled() throws Exc @Test public void requestWithNetMethodShouldSucceedWhenNetApiIsEnabled() throws Exception { - service = createJsonRpcHttpServiceWithRpcApis(RpcApis.NET); + service = createJsonRpcHttpServiceWithRpcApis(RpcApis.NET.name()); final String id = "123"; final RequestBody body = RequestBody.create( @@ -140,7 +140,7 @@ public void requestWithNetMethodShouldSucceedWhenNetApiIsEnabled() throws Except @Test public void requestWithNetMethodShouldSuccessWithCode200WhenNetApiIsNotEnabled() throws Exception { - service = createJsonRpcHttpServiceWithRpcApis(RpcApis.WEB3); + service = createJsonRpcHttpServiceWithRpcApis(RpcApis.WEB3.name()); final String id = "123"; final RequestBody body = RequestBody.create( @@ -159,7 +159,7 @@ public void requestWithNetMethodShouldSuccessWithCode200WhenNetApiIsNotEnabled() @Test public void requestWithNetMethodShouldSucceedWhenNetApiAndOtherIsEnabled() throws Exception { - service = createJsonRpcHttpServiceWithRpcApis(RpcApis.NET, RpcApis.WEB3); + service = createJsonRpcHttpServiceWithRpcApis(RpcApis.NET.name(), RpcApis.WEB3.name()); final String id = "123"; final RequestBody body = RequestBody.create( @@ -171,7 +171,7 @@ public void requestWithNetMethodShouldSucceedWhenNetApiAndOtherIsEnabled() throw } } - private JsonRpcConfiguration createJsonRpcConfigurationWithRpcApis(final RpcApi... rpcApis) { + private JsonRpcConfiguration createJsonRpcConfigurationWithRpcApis(final String... rpcApis) { final JsonRpcConfiguration config = JsonRpcConfiguration.createDefault(); config.setCorsAllowedDomains(singletonList("*")); config.setPort(0); @@ -181,7 +181,7 @@ private JsonRpcConfiguration createJsonRpcConfigurationWithRpcApis(final RpcApi. return config; } - private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final RpcApi... rpcApis) + private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final String... rpcApis) throws Exception { return createJsonRpcHttpServiceWithRpcApis(createJsonRpcConfigurationWithRpcApis(rpcApis)); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java index 2266ee6c1d3..1781824709c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java @@ -82,8 +82,9 @@ public class JsonRpcHttpServiceTestBase { protected static BlockchainQueries blockchainQueries; protected static ChainHead chainHead; protected static Synchronizer synchronizer; - protected static final Collection JSON_RPC_APIS = - Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3, RpcApis.ADMIN); + protected static final Collection JSON_RPC_APIS = + Arrays.asList( + RpcApis.ETH.name(), RpcApis.NET.name(), RpcApis.WEB3.name(), RpcApis.ADMIN.name()); protected static final NatService natService = new NatService(Optional.empty()); protected static int maxConnections = 80; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java index d66049d06ab..39d66773c3c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java @@ -16,9 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIOException; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ETH; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.NET; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.WEB3; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import static org.hyperledger.besu.ethereum.api.tls.KnownClientFileUtil.writeToKnownClientsFile; import static org.hyperledger.besu.ethereum.api.tls.TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration; import static org.hyperledger.besu.ethereum.api.tls.TlsConfiguration.Builder.aTlsConfiguration; @@ -55,10 +53,8 @@ import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -88,7 +84,7 @@ public class JsonRpcHttpServiceTlsClientAuthTest { private static final String JSON_HEADER = "application/json; charset=utf-8"; private static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; private static final BigInteger CHAIN_ID = BigInteger.valueOf(123); - private static final Collection JSON_RPC_APIS = List.of(ETH, NET, WEB3); + private static final NatService natService = new NatService(Optional.empty()); private static final SelfSignedP12Certificate CLIENT_AS_CA_CERT = SelfSignedP12Certificate.create(); @@ -131,7 +127,7 @@ public void initServer() throws Exception { supportedCapabilities, Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(NodeLocalConfigPermissioningController.class)), - JSON_RPC_APIS, + DEFAULT_RPC_APIS, mock(PrivacyParameters.class), mock(JsonRpcConfiguration.class), mock(WebSocketConfiguration.class), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java index f2040f3b3cc..29eeaf6af42 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java @@ -15,9 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ETH; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.NET; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.WEB3; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import static org.hyperledger.besu.ethereum.api.tls.KnownClientFileUtil.writeToKnownClientsFile; import static org.hyperledger.besu.ethereum.api.tls.TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration; import static org.hyperledger.besu.ethereum.api.tls.TlsConfiguration.Builder.aTlsConfiguration; @@ -54,7 +52,6 @@ import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -78,7 +75,6 @@ public class JsonRpcHttpServiceTlsMisconfigurationTest { private static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; private static final BigInteger CHAIN_ID = BigInteger.valueOf(123); - private static final Collection JSON_RPC_APIS = List.of(ETH, NET, WEB3); private static final NatService natService = new NatService(Optional.empty()); private final SelfSignedP12Certificate besuCertificate = SelfSignedP12Certificate.create(); private Path knownClientsFile; @@ -119,7 +115,7 @@ public void beforeEach() throws IOException { supportedCapabilities, Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(NodeLocalConfigPermissioningController.class)), - JSON_RPC_APIS, + DEFAULT_RPC_APIS, mock(PrivacyParameters.class), mock(JsonRpcConfiguration.class), mock(WebSocketConfiguration.class), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java index 9a96d4f2f7e..484d6ae0733 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java @@ -17,9 +17,7 @@ import static okhttp3.Protocol.HTTP_1_1; import static okhttp3.Protocol.HTTP_2; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ETH; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.NET; -import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.WEB3; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import static org.hyperledger.besu.ethereum.api.tls.TlsConfiguration.Builder.aTlsConfiguration; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -54,10 +52,8 @@ import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -85,7 +81,6 @@ public class JsonRpcHttpServiceTlsTest { private static final String JSON_HEADER = "application/json; charset=utf-8"; private static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; private static final BigInteger CHAIN_ID = BigInteger.valueOf(123); - private static final Collection JSON_RPC_APIS = List.of(ETH, NET, WEB3); private static final NatService natService = new NatService(Optional.empty()); private JsonRpcHttpService service; private String baseUrl; @@ -122,7 +117,7 @@ public void initServer() throws Exception { supportedCapabilities, Optional.of(mock(AccountLocalConfigPermissioningController.class)), Optional.of(mock(NodeLocalConfigPermissioningController.class)), - JSON_RPC_APIS, + DEFAULT_RPC_APIS, mock(PrivacyParameters.class), mock(JsonRpcConfiguration.class), mock(WebSocketConfiguration.class), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModulesTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModulesTest.java index c20b1b5c50b..8839aa3a66c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModulesTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/RpcModulesTest.java @@ -36,7 +36,7 @@ public class RpcModulesTest { @Before public void setUp() { - method = new RpcModules(ImmutableList.of(RpcApis.DEBUG)); + method = new RpcModules(ImmutableList.of(RpcApis.DEBUG.name())); } @Test diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java index d79cd06ea14..cb92f062737 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java @@ -19,7 +19,6 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVACY_NOT_ENABLED; import static org.mockito.Mockito.when; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -189,8 +188,8 @@ protected Map create( } @Override - protected RpcApi getApiGroup() { - return RpcApis.PRIV; + protected String getApiGroup() { + return RpcApis.PRIV.name(); } } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfigurationTest.java index e76ab47d4d6..37271e94286 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfigurationTest.java @@ -15,8 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.websocket; import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; +import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS; import org.junit.Test; @@ -29,8 +28,7 @@ public void defaultConfiguration() { assertThat(configuration.isEnabled()).isFalse(); assertThat(configuration.getHost()).isEqualTo("127.0.0.1"); assertThat(configuration.getPort()).isEqualTo(8546); - assertThat(configuration.getRpcApis()) - .containsExactlyInAnyOrder(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); + assertThat(configuration.getRpcApis()).containsExactlyInAnyOrderElementsOf(DEFAULT_RPC_APIS); assertThat(configuration.getMaxActiveConnections()) .isEqualTo(WebSocketConfiguration.DEFAULT_MAX_ACTIVE_CONNECTIONS); } diff --git a/ethereum/evmtool/build.gradle b/ethereum/evmtool/build.gradle index a746548f5ff..f1bf4485742 100644 --- a/ethereum/evmtool/build.gradle +++ b/ethereum/evmtool/build.gradle @@ -38,6 +38,7 @@ dependencies { implementation project(':consensus:clique') implementation project(':consensus:common') implementation project(':consensus:ibft') + implementation project(':consensus:qbft') implementation project(':ethereum:api') implementation project(':ethereum:core') implementation project(':ethereum:referencetests') diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java index 2563c4cdb3e..2746d2e4332 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java @@ -106,6 +106,8 @@ private static GenesisFileModule createGenesisModule(final String genesisConfig) return new IBFTGenesisFileModule(genesisConfig); } else if (config.containsKey("clique")) { return new CliqueGenesisFileModule(genesisConfig); + } else if (config.containsKey("qbft")) { + return new QBFTGenesisFileModule(genesisConfig); } else { // default is mainnet return new MainnetGenesisFileModule(genesisConfig); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java new file mode 100644 index 00000000000..44a54298f64 --- /dev/null +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java @@ -0,0 +1,45 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evmtool; + +import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; +import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; +import org.hyperledger.besu.consensus.qbft.QbftProtocolSchedule; +import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; + +import javax.inject.Named; + +class QBFTGenesisFileModule extends GenesisFileModule { + final QbftExtraDataCodec bftExtraDataEncoder; + + QBFTGenesisFileModule(final String genesisConfig) { + super(genesisConfig); + bftExtraDataEncoder = new QbftExtraDataCodec(); + } + + @Override + ProtocolSchedule provideProtocolSchedule( + final GenesisConfigOptions configOptions, + @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { + return QbftProtocolSchedule.create(configOptions, revertReasonEnabled, bftExtraDataEncoder); + } + + @Override + BlockHeaderFunctions blockHashFunction() { + return BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataEncoder); + } +} diff --git a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AbstractNodeSmartContractPermissioningController.java b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AbstractNodeSmartContractPermissioningController.java index 472701c8999..7f5b629113a 100644 --- a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AbstractNodeSmartContractPermissioningController.java +++ b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AbstractNodeSmartContractPermissioningController.java @@ -73,7 +73,7 @@ protected AbstractNodeSmartContractPermissioningController( * * @param sourceEnode The enode url of the node initiating the connection * @param destinationEnode The enode url of the node receiving the connection - * @return boolean of whether or not to permit the connection to occur + * @return boolean of whether to permit the connection */ @Override public boolean isConnectionPermitted( diff --git a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractV2PermissioningController.java b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractV2PermissioningController.java index 087b3363624..250aa61e315 100644 --- a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractV2PermissioningController.java +++ b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractV2PermissioningController.java @@ -61,11 +61,11 @@ boolean checkSmartContractRules(final EnodeURL sourceEnode, final EnodeURL desti private boolean isPermitted(final EnodeURL enode) { final boolean isIpEnodePermitted = getCallResult(enode); - LOG.info(String.format("Permitted? %s for IP %s", isIpEnodePermitted, enode)); + LOG.trace("Permitted? {} for IP {}", isIpEnodePermitted, enode); if (isIpEnodePermitted) return true; final EnodeURL ipToDNSEnode = ipToDNS(enode); final boolean isIpToDNSEnodePermitted = getCallResult(ipToDNSEnode); - LOG.info(String.format("Permitted? %s for DNS %s", isIpToDNSEnodePermitted, ipToDNSEnode)); + LOG.trace("Permitted? {} for DNS {}", isIpToDNSEnodePermitted, ipToDNSEnode); return isIpToDNSEnodePermitted; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/MutableWorldView.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/MutableWorldView.java index 84eada5a2d1..dc9bd381e8f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/MutableWorldView.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/MutableWorldView.java @@ -17,7 +17,7 @@ public interface MutableWorldView extends WorldView { /** - * Creates a updater for this mutable world view. + * Creates an updater for this mutable world view. * * @return a new updater for this mutable world view. On commit, change made to this updater will * become visible on this view. diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index c3df33a0121..507b14dfcdf 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -64,7 +64,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'zpv92JZmlU6gPifGcPG5ATE6Lv/ruWdJtjLk3EVXO4g=' + knownHash = 'nYb32ASSettoae0o+E+aOhGv7BvkRTXWr8/PlWlWmEA=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/RpcEndpointService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/RpcEndpointService.java new file mode 100644 index 00000000000..73f43a1017a --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/RpcEndpointService.java @@ -0,0 +1,57 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.plugin.services; + +import org.hyperledger.besu.plugin.services.rpc.PluginRpcRequest; + +import java.util.function.Function; + +/** + * This service allows you to add functions exposed via RPC endpoints. + * + *

This service will be available during the registration callback and must be used during the + * registration callback. RPC endpoints are configured prior to the start callback and all endpoints + * connected. No endpoint will actually be called prior to the start callback so initialization + * unrelated to the callback registration can also be done at that time. + */ +public interface RpcEndpointService extends BesuService { + + /** + * Register a function as an RPC endpoint exposed via JSON-RPC. + * + *

The mechanism is a Java function that takes a list of Strings and returns any Java object, + * registered in a specific namespace with a function name. + * + *

The resulting endpoint is the {@code namespace} and the {@code functionName} concatenated + * with an underscore to create the JSON-RPC method name. + * + *

The function takes a {@link PluginRpcRequest} which contains a list of the inputs expressed + * entirely as strings. Javascript numbers are converted to strings via their toString method, and + * complex input objects are not supported. + * + *

The output is a Java object, primitive, or array that will be inspected via Jackson databind. In general if + * JavaBeans naming patterns are followed those names will be reflected in the returned JSON + * object. If the method throws an exception the return is an error with an INTERNAL_ERROR + * treatment. + * + * @param namespace The namespace of the method, must be alphanumeric. + * @param functionName The name of the function, must be alphanumeric. + * @param function The function itself. + * @param specified type of return object + */ + void registerRPCEndpoint( + String namespace, String functionName, Function function); +} diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftRpcApis.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.java similarity index 59% rename from consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftRpcApis.java rename to plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.java index e5840ca8803..c1835bb9f5e 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftRpcApis.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.java @@ -12,20 +12,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.ibft.jsonrpc; +package org.hyperledger.besu.plugin.services.rpc; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; - -import java.util.Optional; - -public class IbftRpcApis { - public static final RpcApi IBFT = new RpcApi("IBFT"); - - public static final Optional valueOf(final String name) { - if (name.equals(IBFT.getCliValue())) { - return Optional.of(IBFT); - } else { - return Optional.empty(); - } - } +public interface PluginRpcRequest { + Object[] getParams(); }