Add mainnet launcher (#1522)

Add a launcher to easily configure the Besu client on the mainnet.
Signed-off-by: Karim TAAM <t2am.karim@gmail.com>
pull/1831/head
matkt 4 years ago committed by GitHub
parent e52222abb9
commit 89fd7aee97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 2
      besu/build.gradle
  3. 35
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  4. 54
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/LauncherOptions.java
  5. 187
      besu/src/main/resources/org/hyperledger/besu/cli/launcher.json
  6. 16
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  7. 5
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  8. 1
      build.gradle
  9. 4
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcApis.java
  10. 1
      gradle/versions.gradle

@ -8,7 +8,8 @@
### Additions and Improvements
* Removed unused flags in default genesis configs [\#1812](https://github.com/hyperledger/besu/pull/1812)
* `--skip-pow-validation-enabled` is now an error with `block import --format JSON`. This is because the JSON format doesn't include the nonce so the proof of work must be calculated. [\#1815](https://github.com/hyperledger/besu/pull/1815)
* Added a new CLI option `--Xlauncher` to start a mainnet launcher. It will help to configure Besu easily.
### Bug Fixes
### Early Access Features

@ -68,7 +68,7 @@ dependencies {
implementation 'org.apache.tuweni:units'
implementation 'org.springframework.security:spring-security-crypto'
implementation 'org.xerial.snappy:snappy-java'
implementation 'net.consensys.services:quorum-mainnet-launcher'
runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
runtimeOnly 'org.apache.logging.log4j:log4j-jul'

@ -52,6 +52,7 @@ import org.hyperledger.besu.cli.options.unstable.DataStorageOptions;
import org.hyperledger.besu.cli.options.unstable.DnsOptions;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
import org.hyperledger.besu.cli.options.unstable.EthstatsOptions;
import org.hyperledger.besu.cli.options.unstable.LauncherOptions;
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
import org.hyperledger.besu.cli.options.unstable.MiningOptions;
import org.hyperledger.besu.cli.options.unstable.NatOptions;
@ -190,6 +191,10 @@ import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.DecodeException;
import io.vertx.core.metrics.MetricsOptions;
import net.consensys.quorum.mainnet.launcher.LauncherManager;
import net.consensys.quorum.mainnet.launcher.config.ImmutableLauncherConfig;
import net.consensys.quorum.mainnet.launcher.exception.LauncherException;
import net.consensys.quorum.mainnet.launcher.util.ParseArgsHelper;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -241,6 +246,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final NatOptions unstableNatOptions = NatOptions.create();
private final NativeLibraryOptions unstableNativeLibraryOptions = NativeLibraryOptions.create();
private final RPCOptions unstableRPCOptions = RPCOptions.create();
final LauncherOptions unstableLauncherOptions = LauncherOptions.create();
private final RunnerBuilder runnerBuilder;
private final BesuController.Builder controllerBuilderFactory;
@ -1131,6 +1137,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final BesuExceptionHandler exceptionHandler,
final InputStream in,
final String... args) {
commandLine =
new CommandLine(this, new BesuCommandCustomFactory(besuPluginContext))
.setCaseInsensitiveEnumValuesAllowed(true);
@ -1145,6 +1152,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
@Override
public void run() {
try {
configureLogging(true);
configureNativeLibs();
@ -1228,6 +1236,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.put("Mining", unstableMiningOptions)
.put("Native Library", unstableNativeLibraryOptions)
.put("Data Storage Options", unstableDataStorageOptions)
.put("Launcher", unstableLauncherOptions)
.build();
UnstableOptionsSubCommand.createUnstableOptions(commandLine, unstableOptions);
@ -1270,10 +1279,34 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
// Create a handler that will search for a config file option and use it for
// default values
// and eventually it will run regular parsing of the remaining options.
final ConfigOptionSearchAndRunHandler configParsingHandler =
new ConfigOptionSearchAndRunHandler(
resultHandler, exceptionHandler, CONFIG_FILE_OPTION_NAME, environment);
commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args);
ParseArgsHelper.getLauncherOptions(unstableLauncherOptions, args);
if (unstableLauncherOptions.isLauncherMode()
|| unstableLauncherOptions.isLauncherModeForced()) {
try {
final ImmutableLauncherConfig launcherConfig =
ImmutableLauncherConfig.builder()
.launcherScript(BesuCommand.class.getResourceAsStream("launcher.json"))
.addCommandClasses(
this, unstableNatOptions, unstableEthstatsOptions, unstableMiningOptions)
.isLauncherForced(unstableLauncherOptions.isLauncherModeForced())
.build();
final File file = new LauncherManager(launcherConfig).run();
logger.info("Config file location : {}", file.getAbsolutePath());
commandLine.parseWithHandlers(
configParsingHandler,
exceptionHandler,
String.format("%s=%s", CONFIG_FILE_OPTION_NAME, file.getAbsolutePath()));
} catch (LauncherException e) {
logger.warn("Unable to run the launcher {}", e.getMessage());
}
} else {
commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args);
}
}
private void startSynchronization() {

@ -0,0 +1,54 @@
/*
* 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.options.unstable;
import net.consensys.quorum.mainnet.launcher.options.Options;
import picocli.CommandLine;
public class LauncherOptions implements Options {
private static final String LAUNCHER_OPTION_NAME = "--Xlauncher";
private static final String LAUNCHER_OPTION_NAME_FORCE = "--Xlauncher-force";
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"})
@CommandLine.Option(
hidden = true,
names = {LAUNCHER_OPTION_NAME},
description =
"Activate the launcher if no configuration file is present. (default: ${DEFAULT-VALUE})",
arity = "0..1")
private Boolean isLauncherMode = Boolean.FALSE;
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"})
@CommandLine.Option(
hidden = true,
names = {LAUNCHER_OPTION_NAME_FORCE},
description =
"Force to activate the launcher even if a configuration file is present. (default: ${DEFAULT-VALUE})",
arity = "0..1")
private Boolean isLauncherModeForced = Boolean.FALSE;
public static LauncherOptions create() {
return new LauncherOptions();
}
public boolean isLauncherMode() {
return isLauncherMode;
}
public boolean isLauncherModeForced() {
return isLauncherModeForced;
}
}

@ -0,0 +1,187 @@
{
"config-file-name": "config.toml",
"steps": [
{
"prompt-type": "LIST",
"question": "Which Ethereum network would you like to use ?",
"config-key": "network",
"available-options": "org.hyperledger.besu.cli.config.NetworkName",
"additional-flag": {
"yolo_v2": "Xberlin-enabled"
}
},
{
"prompt-type": "LIST",
"question": "Which synchronization mode?",
"config-key": "sync-mode",
"available-options": "org.hyperledger.besu.ethereum.eth.sync.SyncMode"
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable pruning?",
"config-key": "pruning-enabled",
"default-option": "no"
},
{
"prompt-type": "INPUT",
"question": "What is the data directory ?",
"config-key": "data-path"
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable the JSON-RPC HTTP service ?",
"config-key": "rpc-http-enabled",
"default-option": "yes",
"sub-questions": [
{
"prompt-type": "CONFIRM",
"question": "Do you want to configure the JSON-RPC options now ?",
"default-option": "yes",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the JSON RPC HTTP host address ?",
"config-key": "rpc-http-host"
},
{
"prompt-type": "INPUT",
"question": "What is the JSON RPC HTTP port ?",
"config-key": "rpc-http-port",
"regex": "[0-9]+"
},
{
"prompt-type": "CHECKBOX",
"question": "Select the list of APIs to enable on JSON-RPC HTTP service",
"config-key": "rpc-http-apis",
"available-options": "org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis$ALL_JSON_RPC_APIS",
"default-option": "ETH, NET, WEB3"
}
]
}
]
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable the JSON-RPC Websocket service ?",
"config-key": "rpc-ws-enabled",
"default-option": "no",
"sub-questions": [
{
"prompt-type": "CONFIRM",
"question": "Do you want to configure the JSON-RPC options now ?",
"default-option": "yes",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the JSON RPC Websocket host address ?",
"config-key": "rpc-ws-host"
},
{
"prompt-type": "INPUT",
"question": "What is the JSON RPC Websocket port ?",
"config-key": "rpc-ws-port",
"regex": "[0-9]+"
},
{
"prompt-type": "CHECKBOX",
"question": "Select the list of APIs to enable on JSON-RPC Websocket service",
"config-key": "rpc-ws-apis",
"available-options": "org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis$ALL_JSON_RPC_APIS",
"default-option": "ETH, NET, WEB3"
}
]
}
]
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable GraphQL functionality ?",
"config-key": "graphql-http-enabled",
"default-option": "no",
"sub-questions": [
{
"prompt-type": "CONFIRM",
"question": "Do you want to configure the GraphQL options now ?",
"default-option": "yes",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the GraphQL host address ?",
"config-key": "graphql-http-host"
},
{
"prompt-type": "INPUT",
"question": "What is the GraphQL port ?",
"config-key": "graphql-http-port",
"regex": "[0-9]+"
}
]
}
]
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to use Ethstats ?",
"default-option": "no",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the URL of Ethstats (nodename:secret@host:port) ?",
"config-key": "Xethstats",
"regex": "([-\\w]+):([\\w]+)?@([-.\\w]+):([\\d]+)"
},
{
"prompt-type": "INPUT",
"question": "What is the contact address ?",
"config-key": "Xethstats-contact"
}
]
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable NAT ?",
"default-option": "no",
"sub-questions": [
{
"prompt-type": "LIST",
"question": "Which NAT method would you like to use ?",
"config-key": "nat-method",
"available-options": "org.hyperledger.besu.nat.NatMethod"
}
]
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to enable mining ?",
"default-option": "no",
"config-key": "miner-enabled",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the account to which mining rewards are paid ?",
"config-key": "miner-coinbase",
"regex": "^0x[0-9a-fA-F]{40}$"
},
{
"prompt-type": "CONFIRM",
"question": "Do you want to use Stratum ?",
"default-option": "no",
"config-key": "miner-stratum-enabled",
"sub-questions": [
{
"prompt-type": "INPUT",
"question": "What is the Stratum host address ?",
"config-key": "miner-stratum-host"
},
{
"prompt-type": "INPUT",
"question": "What is the Stratum port service ?",
"config-key": "miner-stratum-port",
"regex": "[0-9]+"
}
]
}
]
}
]
}

@ -1515,6 +1515,22 @@ public class BesuCommandTest extends CommandTestAbstract {
"The `--Xethstats-contact` requires ethstats server URL to be provided. Either remove --Xethstats-contact or provide an url (via --Xethstats=nodename:secret@host:port)");
}
@Test
public void launcherDefaultOptionValue() {
TestBesuCommand besuCommand = parseCommand();
assertThat(besuCommand.getLauncherOptions().isLauncherMode()).isFalse();
assertThat(besuCommand.getEnodeDnsConfiguration().updateEnabled()).isFalse();
}
@Test
public void launcherOptionIsParsedCorrectly() {
TestBesuCommand besuCommand = parseCommand("--Xlauncher", "true", "--Xlauncher-force", "true");
assertThat(besuCommand.getLauncherOptions().isLauncherMode()).isTrue();
assertThat(besuCommand.getEnodeDnsConfiguration().updateEnabled()).isFalse();
}
@Test
public void dnsEnabledOptionIsParsedCorrectly() {
final TestBesuCommand besuCommand = parseCommand("--Xdns-enabled", "true");

@ -32,6 +32,7 @@ import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
import org.hyperledger.besu.cli.options.unstable.LauncherOptions;
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
import org.hyperledger.besu.cli.options.unstable.NetworkingOptions;
import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions;
@ -407,6 +408,10 @@ public abstract class CommandTestAbstract {
return unstableMetricsCLIOptions;
}
public LauncherOptions getLauncherOptions() {
return unstableLauncherOptions;
}
public void close() {
if (vertx != null) {
final AtomicBoolean closed = new AtomicBoolean(false);

@ -125,6 +125,7 @@ allprojects {
mavenLocal()
maven { url "https://hyperledger-org.bintray.com/besu-repo" }
maven { url "https://consensys.bintray.com/pegasys-repo" }
maven { url "https://consensys.bintray.com/consensys" }
maven { url "https://repo.spring.io/libs-release" }
maven { url "https://dl.bintray.com/open-telemetry/maven" }
}

@ -35,6 +35,10 @@ public class RpcApis {
public static final List<RpcApi> DEFAULT_JSON_RPC_APIS = Arrays.asList(ETH, NET, WEB3);
@SuppressWarnings("unused")
public static final List<RpcApi> ALL_JSON_RPC_APIS =
Arrays.asList(ETH, DEBUG, MINER, NET, PERM, WEB3, ADMIN, EEA, PRIV, TX_POOL, TRACE, PLUGINS);
public static Optional<RpcApi> valueOf(final String name) {
if (name.equals(ETH.getCliValue())) {
return Optional.of(ETH);

@ -113,6 +113,7 @@ dependencyManagement {
dependency 'org.bouncycastle:bcprov-jdk15on:1.68'
dependency 'org.fusesource.jansi:jansi:2.1.1'
dependency 'net.consensys.services:quorum-mainnet-launcher:1.0.1'
dependency 'org.hyperledger.besu:bls12-381:0.3.0'
dependency 'org.hyperledger.besu:secp256k1:0.3.0'

Loading…
Cancel
Save