Simplifying BesuCommand step 1 (#7682)

Simplifying BesuCommand
---------

Signed-off-by: Justin Florentine <justin+github@florentine.us>
pull/7745/head
Justin Florentine 2 months ago committed by GitHub
parent 94099d18f5
commit f4dc48d94d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java
  2. 305
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  3. 3
      besu/src/main/java/org/hyperledger/besu/cli/options/DataStorageOptions.java
  4. 1
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/ApiConfigurationOptions.java
  5. 36
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/EngineRPCConfiguration.java
  6. 81
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/EngineRPCOptions.java
  7. 1
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/GraphQlOptions.java
  8. 34
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java
  9. 1
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptionGroup.java
  10. 238
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/P2PDiscoveryOptions.java
  11. 1
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/PermissionsOptions.java
  12. 1
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MetricsCLIOptions.java
  13. 2
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/P2PTLSConfigOptions.java
  14. 4
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java
  15. 16
      besu/src/main/java/org/hyperledger/besu/components/BesuCommandModule.java
  16. 2
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  17. 1
      besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java
  18. 2
      config/src/main/java/org/hyperledger/besu/config/MergeConfigOptions.java
  19. 39
      ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/P2PDiscoveryConfiguration.java

@ -17,8 +17,8 @@ package org.hyperledger.besu.tests.acceptance.dsl.node;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.cli.options.DataStorageOptions;
import org.hyperledger.besu.cli.options.TransactionPoolOptions; import org.hyperledger.besu.cli.options.TransactionPoolOptions;
import org.hyperledger.besu.cli.options.stable.DataStorageOptions;
import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions;
import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;

@ -24,7 +24,6 @@ import static org.hyperledger.besu.cli.config.NetworkName.MAINNET;
import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG; import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.isOptionSet; import static org.hyperledger.besu.cli.util.CommandLineUtils.isOptionSet;
import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE; import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE;
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER; import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
@ -38,22 +37,22 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.cli.config.ProfilesCompletionCandidates; import org.hyperledger.besu.cli.config.ProfilesCompletionCandidates;
import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.converter.MetricCategoryConverter;
import org.hyperledger.besu.cli.converter.PercentageConverter;
import org.hyperledger.besu.cli.converter.SubnetInfoConverter;
import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty; import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler; import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler;
import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler; import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler;
import org.hyperledger.besu.cli.options.DataStorageOptions;
import org.hyperledger.besu.cli.options.MiningOptions; import org.hyperledger.besu.cli.options.MiningOptions;
import org.hyperledger.besu.cli.options.TransactionPoolOptions; import org.hyperledger.besu.cli.options.TransactionPoolOptions;
import org.hyperledger.besu.cli.options.stable.ApiConfigurationOptions; import org.hyperledger.besu.cli.options.stable.ApiConfigurationOptions;
import org.hyperledger.besu.cli.options.stable.DataStorageOptions; import org.hyperledger.besu.cli.options.stable.EngineRPCConfiguration;
import org.hyperledger.besu.cli.options.stable.EngineRPCOptions;
import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.cli.options.stable.EthstatsOptions;
import org.hyperledger.besu.cli.options.stable.GraphQlOptions; import org.hyperledger.besu.cli.options.stable.GraphQlOptions;
import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions; import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions;
import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; import org.hyperledger.besu.cli.options.stable.LoggingLevelOption;
import org.hyperledger.besu.cli.options.stable.MetricsOptionGroup; import org.hyperledger.besu.cli.options.stable.MetricsOptionGroup;
import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption; import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption;
import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions; import org.hyperledger.besu.cli.options.stable.P2PDiscoveryOptions;
import org.hyperledger.besu.cli.options.stable.PermissionsOptions; import org.hyperledger.besu.cli.options.stable.PermissionsOptions;
import org.hyperledger.besu.cli.options.stable.PluginsConfigurationOptions; import org.hyperledger.besu.cli.options.stable.PluginsConfigurationOptions;
import org.hyperledger.besu.cli.options.stable.RpcWebsocketOptions; import org.hyperledger.besu.cli.options.stable.RpcWebsocketOptions;
@ -67,6 +66,7 @@ import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
import org.hyperledger.besu.cli.options.unstable.NatOptions; import org.hyperledger.besu.cli.options.unstable.NatOptions;
import org.hyperledger.besu.cli.options.unstable.NativeLibraryOptions; import org.hyperledger.besu.cli.options.unstable.NativeLibraryOptions;
import org.hyperledger.besu.cli.options.unstable.NetworkingOptions; import org.hyperledger.besu.cli.options.unstable.NetworkingOptions;
import org.hyperledger.besu.cli.options.unstable.P2PTLSConfigOptions;
import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions; import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions;
import org.hyperledger.besu.cli.options.unstable.RPCOptions; import org.hyperledger.besu.cli.options.unstable.RPCOptions;
import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions; import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions;
@ -124,6 +124,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolCo
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.mainnet.FrontierTargetingGasLimitCalculator; import org.hyperledger.besu.ethereum.mainnet.FrontierTargetingGasLimitCalculator;
import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration;
import org.hyperledger.besu.ethereum.p2p.discovery.P2PDiscoveryConfiguration;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.p2p.peers.StaticNodesParser; import org.hyperledger.besu.ethereum.p2p.peers.StaticNodesParser;
@ -209,7 +210,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
@ -247,7 +247,6 @@ import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions; import io.vertx.core.VertxOptions;
import io.vertx.core.json.DecodeException; import io.vertx.core.json.DecodeException;
import io.vertx.core.metrics.MetricsOptions; import io.vertx.core.metrics.MetricsOptions;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -416,7 +415,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
// P2P Discovery Option Group // P2P Discovery Option Group
@CommandLine.ArgGroup(validate = false, heading = "@|bold P2P Discovery Options|@%n") @CommandLine.ArgGroup(validate = false, heading = "@|bold P2P Discovery Options|@%n")
P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup(); P2PDiscoveryOptions p2PDiscoveryOptions = new P2PDiscoveryOptions();
P2PDiscoveryConfiguration p2PDiscoveryConfig;
private final TransactionSelectionServiceImpl transactionSelectionServiceImpl; private final TransactionSelectionServiceImpl transactionSelectionServiceImpl;
private final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl; private final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl;
@ -424,163 +425,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final BlockchainServiceImpl blockchainServiceImpl; private final BlockchainServiceImpl blockchainServiceImpl;
private BesuComponent besuComponent; private BesuComponent besuComponent;
static class P2PDiscoveryOptionGroup {
// Public IP stored to prevent having to research it each time we need it.
private InetAddress autoDiscoveredDefaultIP = null;
// Completely disables P2P within Besu.
@Option(
names = {"--p2p-enabled"},
description = "Enable P2P functionality (default: ${DEFAULT-VALUE})",
arity = "1")
private final Boolean p2pEnabled = true;
// Boolean option to indicate if peers should NOT be discovered, default to
// false indicates that
// the peers should be discovered by default.
//
// This negative option is required because of the nature of the option that is
// true when
// added on the command line. You can't do --option=false, so false is set as
// default
// and you have not to set the option at all if you want it false.
// This seems to be the only way it works with Picocli.
// Also many other software use the same negative option scheme for false
// defaults
// meaning that it's probably the right way to handle disabling options.
@Option(
names = {"--discovery-enabled"},
description = "Enable P2P discovery (default: ${DEFAULT-VALUE})",
arity = "1")
private final Boolean peerDiscoveryEnabled = true;
// A list of bootstrap nodes can be passed
// and a hardcoded list will be used otherwise by the Runner.
// NOTE: we have no control over default value here.
@Option(
names = {"--bootnodes"},
paramLabel = "<enode://id@host:port>",
description =
"Comma separated enode URLs for P2P discovery bootstrap. "
+ "Default is a predefined list.",
split = ",",
arity = "0..*")
private final List<String> bootNodes = null;
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--p2p-host"},
paramLabel = MANDATORY_HOST_FORMAT_HELP,
description = "IP address this node advertises to its peers (default: ${DEFAULT-VALUE})",
arity = "1")
private String p2pHost = autoDiscoverDefaultIP().getHostAddress();
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--p2p-interface"},
paramLabel = MANDATORY_HOST_FORMAT_HELP,
description =
"The network interface address on which this node listens for P2P communication (default: ${DEFAULT-VALUE})",
arity = "1")
private String p2pInterface = NetworkUtility.INADDR_ANY;
@Option(
names = {"--p2p-port"},
paramLabel = MANDATORY_PORT_FORMAT_HELP,
description = "Port on which to listen for P2P communication (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer p2pPort = EnodeURLImpl.DEFAULT_LISTENING_PORT;
@Option(
names = {"--max-peers", "--p2p-peer-upper-bound"},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description = "Maximum P2P connections that can be established (default: ${DEFAULT-VALUE})")
private final Integer maxPeers = DEFAULT_MAX_PEERS;
@Option(
names = {"--remote-connections-limit-enabled"},
description =
"Whether to limit the number of P2P connections initiated remotely. (default: ${DEFAULT-VALUE})")
private final Boolean isLimitRemoteWireConnectionsEnabled = true;
@Option(
names = {"--remote-connections-max-percentage"},
paramLabel = MANDATORY_DOUBLE_FORMAT_HELP,
description =
"The maximum percentage of P2P connections that can be initiated remotely. Must be between 0 and 100 inclusive. (default: ${DEFAULT-VALUE})",
arity = "1",
converter = PercentageConverter.class)
private final Percentage maxRemoteConnectionsPercentage =
Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED).toPercentage();
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
names = {"--discovery-dns-url"},
description = "Specifies the URL to use for DNS discovery")
private String discoveryDnsUrl = null;
@Option(
names = {"--random-peer-priority-enabled"},
description =
"Allow for incoming connections to be prioritized randomly. This will prevent (typically small, stable) networks from forming impenetrable peer cliques. (default: ${DEFAULT-VALUE})")
private final Boolean randomPeerPriority = Boolean.FALSE;
@Option(
names = {"--banned-node-ids", "--banned-node-id"},
paramLabel = MANDATORY_NODE_ID_FORMAT_HELP,
description = "A list of node IDs to ban from the P2P network.",
split = ",",
arity = "1..*")
void setBannedNodeIds(final List<String> values) {
try {
bannedNodeIds =
values.stream()
.filter(value -> !value.isEmpty())
.map(EnodeURLImpl::parseNodeId)
.collect(Collectors.toList());
} catch (final IllegalArgumentException e) {
throw new ParameterException(
new CommandLine(this),
"Invalid ids supplied to '--banned-node-ids'. " + e.getMessage());
}
}
// Boolean option to set that in a PoA network the bootnodes should always be queried during
// peer table refresh. If this flag is disabled bootnodes are only sent FINDN requests on first
// startup, meaning that an offline bootnode or network outage at the client can prevent it
// discovering any peers without a restart.
@Option(
names = {"--poa-discovery-retry-bootnodes"},
description =
"Always use of bootnodes for discovery in PoA networks. Disabling this reverts "
+ " to the same behaviour as non-PoA networks, where neighbours are only discovered from bootnodes on first startup."
+ "(default: ${DEFAULT-VALUE})",
arity = "1")
private final Boolean poaDiscoveryRetryBootnodes = true;
private Collection<Bytes> bannedNodeIds = new ArrayList<>();
// Used to discover the default IP of the client.
// Loopback IP is used by default as this is how smokeTests require it to be
// and it's probably a good security behaviour to default only on the localhost.
private InetAddress autoDiscoverDefaultIP() {
autoDiscoveredDefaultIP =
Optional.ofNullable(autoDiscoveredDefaultIP).orElseGet(InetAddress::getLoopbackAddress);
return autoDiscoveredDefaultIP;
}
@Option(
names = {"--net-restrict"},
arity = "1..*",
split = ",",
converter = SubnetInfoConverter.class,
description =
"Comma-separated list of allowed IP subnets (e.g., '192.168.1.0/24,10.0.0.0/8').")
private List<SubnetInfo> allowedSubnets;
}
@Option( @Option(
names = {"--sync-mode"}, names = {"--sync-mode"},
paramLabel = MANDATORY_MODE_FORMAT_HELP, paramLabel = MANDATORY_MODE_FORMAT_HELP,
@ -647,42 +491,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
// Engine JSON-PRC Options // Engine JSON-PRC Options
@CommandLine.ArgGroup(validate = false, heading = "@|bold Engine JSON-RPC Options|@%n") @CommandLine.ArgGroup(validate = false, heading = "@|bold Engine JSON-RPC Options|@%n")
EngineRPCOptionGroup engineRPCOptionGroup = new EngineRPCOptionGroup(); EngineRPCOptions engineRPCOptions = new EngineRPCOptions();
static class EngineRPCOptionGroup {
@Option(
names = {"--engine-rpc-enabled"},
description =
"enable the engine api, even in the absence of merge-specific configurations.")
private final Boolean overrideEngineRpcEnabled = false;
@Option(
names = {"--engine-rpc-port", "--engine-rpc-http-port"},
paramLabel = MANDATORY_PORT_FORMAT_HELP,
description = "Port to provide consensus client APIS on (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer engineRpcPort = DEFAULT_ENGINE_JSON_RPC_PORT;
@Option( EngineRPCConfiguration engineRPCConfig = engineRPCOptions.toDomainObject();
names = {"--engine-jwt-secret"},
paramLabel = MANDATORY_FILE_FORMAT_HELP,
description = "Path to file containing shared secret key for JWT signature verification")
private final Path engineJwtKeyFile = null;
@Option(
names = {"--engine-jwt-disabled"},
description = "Disable authentication for Engine APIs (default: ${DEFAULT-VALUE})")
private final Boolean isEngineAuthDisabled = false;
@Option(
names = {"--engine-host-allowlist"},
paramLabel = "<hostname>[,<hostname>...]... or * or all",
description =
"Comma separated list of hostnames to allow for ENGINE API access (applies to both HTTP and websockets), or * to accept any host (default: ${DEFAULT-VALUE})",
defaultValue = "localhost,127.0.0.1")
private final JsonRPCAllowlistHostsProperty engineHostsAllowlist =
new JsonRPCAllowlistHostsProperty();
}
// JSON-RPC HTTP Options // JSON-RPC HTTP Options
@CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC HTTP Options|@%n") @CommandLine.ArgGroup(validate = false, heading = "@|bold JSON-RPC HTTP Options|@%n")
@ -1409,13 +1220,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private Runner buildRunner() { private Runner buildRunner() {
return synchronize( return synchronize(
besuController, besuController,
p2PDiscoveryOptionGroup.p2pEnabled, p2PDiscoveryConfig.p2pEnabled(),
p2pTLSConfiguration, p2pTLSConfiguration,
p2PDiscoveryOptionGroup.peerDiscoveryEnabled, p2PDiscoveryConfig.peerDiscoveryEnabled(),
ethNetworkConfig, ethNetworkConfig,
p2PDiscoveryOptionGroup.p2pHost, p2PDiscoveryConfig.p2pHost(),
p2PDiscoveryOptionGroup.p2pInterface, p2PDiscoveryConfig.p2pInterface(),
p2PDiscoveryOptionGroup.p2pPort, p2PDiscoveryConfig.p2pPort(),
graphQLConfiguration, graphQLConfiguration,
jsonRpcConfiguration, jsonRpcConfiguration,
engineJsonRpcConfiguration, engineJsonRpcConfiguration,
@ -1614,7 +1425,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private void validateOptions() { private void validateOptions() {
validateRequiredOptions(); validateRequiredOptions();
issueOptionWarnings(); issueOptionWarnings();
validateP2PInterface(p2PDiscoveryOptionGroup.p2pInterface); validateP2PInterface(p2PDiscoveryOptions.p2pInterface);
validateMiningParams(); validateMiningParams();
validateNatParams(); validateNatParams();
validateNetStatsParams(); validateNetStatsParams();
@ -1750,13 +1561,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
private void ensureValidPeerBoundParams() { private void ensureValidPeerBoundParams() {
maxPeers = p2PDiscoveryOptionGroup.maxPeers; maxPeers = p2PDiscoveryOptions.maxPeers;
final Boolean isLimitRemoteWireConnectionsEnabled = final Boolean isLimitRemoteWireConnectionsEnabled =
p2PDiscoveryOptionGroup.isLimitRemoteWireConnectionsEnabled; p2PDiscoveryOptions.isLimitRemoteWireConnectionsEnabled;
if (isLimitRemoteWireConnectionsEnabled) { if (isLimitRemoteWireConnectionsEnabled) {
final float fraction = final float fraction =
Fraction.fromPercentage(p2PDiscoveryOptionGroup.maxRemoteConnectionsPercentage) Fraction.fromPercentage(p2PDiscoveryOptions.maxRemoteConnectionsPercentage).getValue();
.getValue();
checkState( checkState(
fraction >= 0.0 && fraction <= 1.0, fraction >= 0.0 && fraction <= 1.0,
"Fraction of remote connections allowed must be between 0.0 and 1.0 (inclusive)."); "Fraction of remote connections allowed must be between 0.0 and 1.0 (inclusive).");
@ -1820,7 +1630,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
logger, logger,
commandLine, commandLine,
"--p2p-enabled", "--p2p-enabled",
!p2PDiscoveryOptionGroup.p2pEnabled, !p2PDiscoveryOptions.p2pEnabled,
asList( asList(
"--bootnodes", "--bootnodes",
"--discovery-enabled", "--discovery-enabled",
@ -1861,6 +1671,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
private void configure() throws Exception { private void configure() throws Exception {
p2PDiscoveryConfig = p2PDiscoveryOptions.toDomainObject();
engineRPCConfig = engineRPCOptions.toDomainObject();
checkPortClash(); checkPortClash();
checkIfRequiredPortsAreAvailable(); checkIfRequiredPortsAreAvailable();
syncMode = getDefaultSyncModeIfNotSet(); syncMode = getDefaultSyncModeIfNotSet();
@ -1870,25 +1682,18 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
jsonRpcConfiguration = jsonRpcConfiguration =
jsonRpcHttpOptions.jsonRpcConfiguration( jsonRpcHttpOptions.jsonRpcConfiguration(
hostsAllowlist, hostsAllowlist, p2PDiscoveryOptions.p2pHost, unstableRPCOptions.getHttpTimeoutSec());
p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress(),
unstableRPCOptions.getHttpTimeoutSec());
if (isEngineApiEnabled()) { if (isEngineApiEnabled()) {
engineJsonRpcConfiguration = engineJsonRpcConfiguration = createEngineJsonRpcConfiguration();
createEngineJsonRpcConfiguration(
engineRPCOptionGroup.engineRpcPort, engineRPCOptionGroup.engineHostsAllowlist);
} }
p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine); p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine);
graphQLConfiguration = graphQLConfiguration =
graphQlOptions.graphQLConfiguration( graphQlOptions.graphQLConfiguration(
hostsAllowlist, hostsAllowlist, p2PDiscoveryOptions.p2pHost, unstableRPCOptions.getHttpTimeoutSec());
p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress(),
unstableRPCOptions.getHttpTimeoutSec());
webSocketConfiguration = webSocketConfiguration =
rpcWebsocketOptions.webSocketConfiguration( rpcWebsocketOptions.webSocketConfiguration(
hostsAllowlist, hostsAllowlist, p2PDiscoveryConfig.p2pHost(), unstableRPCOptions.getWsTimeoutSec());
p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress(),
unstableRPCOptions.getWsTimeoutSec());
jsonRpcIpcConfiguration = jsonRpcIpcConfiguration =
jsonRpcIpcConfiguration( jsonRpcIpcConfiguration(
unstableIpcOptions.isEnabled(), unstableIpcOptions.isEnabled(),
@ -2008,32 +1813,31 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.requiredBlocks(requiredBlocks) .requiredBlocks(requiredBlocks)
.reorgLoggingThreshold(reorgLoggingThreshold) .reorgLoggingThreshold(reorgLoggingThreshold)
.evmConfiguration(unstableEvmOptions.toDomainObject()) .evmConfiguration(unstableEvmOptions.toDomainObject())
.maxPeers(p2PDiscoveryOptionGroup.maxPeers) .maxPeers(p2PDiscoveryOptions.maxPeers)
.maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers) .maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers)
.randomPeerPriority(p2PDiscoveryOptionGroup.randomPeerPriority) .randomPeerPriority(p2PDiscoveryOptions.randomPeerPriority)
.chainPruningConfiguration(unstableChainPruningOptions.toDomainObject()) .chainPruningConfiguration(unstableChainPruningOptions.toDomainObject())
.cacheLastBlocks(numberOfblocksToCache) .cacheLastBlocks(numberOfblocksToCache)
.genesisStateHashCacheEnabled(genesisStateHashCacheEnabled) .genesisStateHashCacheEnabled(genesisStateHashCacheEnabled)
.besuComponent(besuComponent); .besuComponent(besuComponent);
} }
private JsonRpcConfiguration createEngineJsonRpcConfiguration( private JsonRpcConfiguration createEngineJsonRpcConfiguration() {
final Integer engineListenPort, final List<String> allowCallsFrom) {
jsonRpcHttpOptions.checkDependencies(logger, commandLine); jsonRpcHttpOptions.checkDependencies(logger, commandLine);
final JsonRpcConfiguration engineConfig = final JsonRpcConfiguration engineConfig =
jsonRpcHttpOptions.jsonRpcConfiguration( jsonRpcHttpOptions.jsonRpcConfiguration(
allowCallsFrom, engineRPCConfig.engineHostsAllowlist(),
p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress(), p2PDiscoveryConfig.p2pHost(),
unstableRPCOptions.getWsTimeoutSec()); unstableRPCOptions.getWsTimeoutSec());
engineConfig.setPort(engineListenPort); engineConfig.setPort(engineRPCConfig.engineRpcPort());
engineConfig.setRpcApis(Arrays.asList("ENGINE", "ETH")); engineConfig.setRpcApis(Arrays.asList("ENGINE", "ETH"));
engineConfig.setEnabled(isEngineApiEnabled()); engineConfig.setEnabled(isEngineApiEnabled());
if (!engineRPCOptionGroup.isEngineAuthDisabled) { if (!engineRPCConfig.isEngineAuthDisabled()) {
engineConfig.setAuthenticationEnabled(true); engineConfig.setAuthenticationEnabled(true);
engineConfig.setAuthenticationAlgorithm(JwtAlgorithm.HS256); engineConfig.setAuthenticationAlgorithm(JwtAlgorithm.HS256);
if (Objects.nonNull(engineRPCOptionGroup.engineJwtKeyFile) if (Objects.nonNull(engineRPCConfig.engineJwtKeyFile())
&& java.nio.file.Files.exists(engineRPCOptionGroup.engineJwtKeyFile)) { && java.nio.file.Files.exists(engineRPCConfig.engineJwtKeyFile())) {
engineConfig.setAuthenticationPublicKeyFile(engineRPCOptionGroup.engineJwtKeyFile.toFile()); engineConfig.setAuthenticationPublicKeyFile(engineRPCConfig.engineJwtKeyFile().toFile());
} else { } else {
logger.warn( logger.warn(
"Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir"); "Engine API authentication enabled without key file. Expect ephemeral jwt.hex file in datadir");
@ -2090,7 +1894,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.enabled(metricsOptionGroup.getMetricsEnabled()) .enabled(metricsOptionGroup.getMetricsEnabled())
.host( .host(
Strings.isNullOrEmpty(metricsOptionGroup.getMetricsHost()) Strings.isNullOrEmpty(metricsOptionGroup.getMetricsHost())
? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() ? p2PDiscoveryOptions.p2pHost
: metricsOptionGroup.getMetricsHost()) : metricsOptionGroup.getMetricsHost())
.port(metricsOptionGroup.getMetricsPort()) .port(metricsOptionGroup.getMetricsPort())
.protocol(metricsOptionGroup.getMetricsProtocol()) .protocol(metricsOptionGroup.getMetricsProtocol())
@ -2098,7 +1902,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.pushEnabled(metricsOptionGroup.getMetricsPushEnabled()) .pushEnabled(metricsOptionGroup.getMetricsPushEnabled())
.pushHost( .pushHost(
Strings.isNullOrEmpty(metricsOptionGroup.getMetricsPushHost()) Strings.isNullOrEmpty(metricsOptionGroup.getMetricsPushHost())
? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress() ? p2PDiscoveryOptions.autoDiscoverDefaultIP().getHostAddress()
: metricsOptionGroup.getMetricsPushHost()) : metricsOptionGroup.getMetricsPushHost())
.pushPort(metricsOptionGroup.getMetricsPushPort()) .pushPort(metricsOptionGroup.getMetricsPushPort())
.pushInterval(metricsOptionGroup.getMetricsPushInterval()) .pushInterval(metricsOptionGroup.getMetricsPushInterval())
@ -2441,7 +2245,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.apiConfiguration(apiConfiguration) .apiConfiguration(apiConfiguration)
.pidPath(pidPath) .pidPath(pidPath)
.dataDir(dataDir()) .dataDir(dataDir())
.bannedNodeIds(p2PDiscoveryOptionGroup.bannedNodeIds) .bannedNodeIds(p2PDiscoveryConfig.bannedNodeIds())
.metricsSystem((ObservableMetricsSystem) besuComponent.getMetricsSystem()) .metricsSystem((ObservableMetricsSystem) besuComponent.getMetricsSystem())
.permissioningService(permissioningService) .permissioningService(permissioningService)
.metricsConfiguration(metricsConfiguration) .metricsConfiguration(metricsConfiguration)
@ -2453,8 +2257,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.storageProvider(keyValueStorageProvider(keyValueStorageName)) .storageProvider(keyValueStorageProvider(keyValueStorageName))
.rpcEndpointService(rpcEndpointServiceImpl) .rpcEndpointService(rpcEndpointServiceImpl)
.enodeDnsConfiguration(getEnodeDnsConfiguration()) .enodeDnsConfiguration(getEnodeDnsConfiguration())
.allowedSubnets(p2PDiscoveryOptionGroup.allowedSubnets) .allowedSubnets(p2PDiscoveryConfig.allowedSubnets())
.poaDiscoveryRetryBootnodes(p2PDiscoveryOptionGroup.poaDiscoveryRetryBootnodes) .poaDiscoveryRetryBootnodes(p2PDiscoveryConfig.poaDiscoveryRetryBootnodes())
.build(); .build();
addShutdownHook(runner); addShutdownHook(runner);
@ -2529,7 +2333,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
} }
if (p2PDiscoveryOptionGroup.bootNodes == null) { if (p2PDiscoveryOptions.bootNodes == null) {
builder.setBootNodes(new ArrayList<>()); builder.setBootNodes(new ArrayList<>());
} }
builder.setDnsDiscoveryUrl(null); builder.setDnsDiscoveryUrl(null);
@ -2541,8 +2345,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
builder.setNetworkId(networkId); builder.setNetworkId(networkId);
} }
if (p2PDiscoveryOptionGroup.discoveryDnsUrl != null) { if (p2PDiscoveryOptions.discoveryDnsUrl != null) {
builder.setDnsDiscoveryUrl(p2PDiscoveryOptionGroup.discoveryDnsUrl); builder.setDnsDiscoveryUrl(p2PDiscoveryOptions.discoveryDnsUrl);
} else { } else {
final Optional<String> discoveryDnsUrlFromGenesis = final Optional<String> discoveryDnsUrlFromGenesis =
genesisConfigOptionsSupplier.get().getDiscoveryOptions().getDiscoveryDnsUrl(); genesisConfigOptionsSupplier.get().getDiscoveryOptions().getDiscoveryDnsUrl();
@ -2550,9 +2354,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
List<EnodeURL> listBootNodes = null; List<EnodeURL> listBootNodes = null;
if (p2PDiscoveryOptionGroup.bootNodes != null) { if (p2PDiscoveryOptions.bootNodes != null) {
try { try {
listBootNodes = buildEnodes(p2PDiscoveryOptionGroup.bootNodes, getEnodeDnsConfiguration()); listBootNodes = buildEnodes(p2PDiscoveryOptions.bootNodes, getEnodeDnsConfiguration());
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
throw new ParameterException(commandLine, e.getMessage()); throw new ParameterException(commandLine, e.getMessage());
} }
@ -2564,7 +2368,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
} }
if (listBootNodes != null) { if (listBootNodes != null) {
if (!p2PDiscoveryOptionGroup.peerDiscoveryEnabled) { if (!p2PDiscoveryOptions.peerDiscoveryEnabled) {
logger.warn("Discovery disabled: bootnodes will be ignored."); logger.warn("Discovery disabled: bootnodes will be ignored.");
} }
DiscoveryConfiguration.assertValidBootnodes(listBootNodes); DiscoveryConfiguration.assertValidBootnodes(listBootNodes);
@ -2699,12 +2503,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.filter(port -> port > 0) .filter(port -> port > 0)
.forEach( .forEach(
port -> { port -> {
if (port.equals(p2PDiscoveryOptionGroup.p2pPort) if (port.equals(p2PDiscoveryConfig.p2pPort())
&& (NetworkUtility.isPortUnavailableForTcp(port) && (NetworkUtility.isPortUnavailableForTcp(port)
|| NetworkUtility.isPortUnavailableForUdp(port))) { || NetworkUtility.isPortUnavailableForUdp(port))) {
unavailablePorts.add(port); unavailablePorts.add(port);
} }
if (!port.equals(p2PDiscoveryOptionGroup.p2pPort) if (!port.equals(p2PDiscoveryConfig.p2pPort())
&& NetworkUtility.isPortUnavailableForTcp(port)) { && NetworkUtility.isPortUnavailableForTcp(port)) {
unavailablePorts.add(port); unavailablePorts.add(port);
} }
@ -2724,15 +2528,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
*/ */
private List<Integer> getEffectivePorts() { private List<Integer> getEffectivePorts() {
final List<Integer> effectivePorts = new ArrayList<>(); final List<Integer> effectivePorts = new ArrayList<>();
addPortIfEnabled( addPortIfEnabled(effectivePorts, p2PDiscoveryOptions.p2pPort, p2PDiscoveryOptions.p2pEnabled);
effectivePorts, p2PDiscoveryOptionGroup.p2pPort, p2PDiscoveryOptionGroup.p2pEnabled);
addPortIfEnabled( addPortIfEnabled(
effectivePorts, graphQlOptions.getGraphQLHttpPort(), graphQlOptions.isGraphQLHttpEnabled()); effectivePorts, graphQlOptions.getGraphQLHttpPort(), graphQlOptions.isGraphQLHttpEnabled());
addPortIfEnabled( addPortIfEnabled(
effectivePorts, jsonRpcHttpOptions.getRpcHttpPort(), jsonRpcHttpOptions.isRpcHttpEnabled()); effectivePorts, jsonRpcHttpOptions.getRpcHttpPort(), jsonRpcHttpOptions.isRpcHttpEnabled());
addPortIfEnabled( addPortIfEnabled(
effectivePorts, rpcWebsocketOptions.getRpcWsPort(), rpcWebsocketOptions.isRpcWsEnabled()); effectivePorts, rpcWebsocketOptions.getRpcWsPort(), rpcWebsocketOptions.isRpcWsEnabled());
addPortIfEnabled(effectivePorts, engineRPCOptionGroup.engineRpcPort, isEngineApiEnabled()); addPortIfEnabled(effectivePorts, engineRPCConfig.engineRpcPort(), isEngineApiEnabled());
addPortIfEnabled( addPortIfEnabled(
effectivePorts, effectivePorts,
metricsOptionGroup.getMetricsPort(), metricsOptionGroup.getMetricsPort(),
@ -2859,7 +2662,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
private boolean isEngineApiEnabled() { private boolean isEngineApiEnabled() {
return engineRPCOptionGroup.overrideEngineRpcEnabled || isMergeEnabled(); return engineRPCConfig.overrideEngineRpcEnabled() || isMergeEnabled();
} }
private SyncMode getDefaultSyncModeIfNotSet() { private SyncMode getDefaultSyncModeIfNotSet() {

@ -12,7 +12,7 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package org.hyperledger.besu.cli.options.stable; package org.hyperledger.besu.cli.options;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
@ -22,7 +22,6 @@ import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils; import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;

@ -28,6 +28,7 @@ import picocli.CommandLine;
* Handles configuration options for the API in Besu, including gas price settings, RPC log range, * Handles configuration options for the API in Besu, including gas price settings, RPC log range,
* and trace filter range. * and trace filter range.
*/ */
// TODO: implement CLIOption<ApiConfiguration>
public class ApiConfigurationOptions { public class ApiConfigurationOptions {
/** Default constructor. */ /** Default constructor. */
public ApiConfigurationOptions() {} public ApiConfigurationOptions() {}

@ -0,0 +1,36 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.stable;
import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
import java.nio.file.Path;
/**
* Command line options for configuring Engine RPC on the node.
*
* @param overrideEngineRpcEnabled enable the engine api, even in the absence of merge-specific
* configurations.
* @param engineRpcPort Port to provide consensus client APIS on
* @param engineJwtKeyFile Path to file containing shared secret key for JWT signature verification
* @param isEngineAuthDisabled Disable authentication for Engine APIs
* @param engineHostsAllowlist List of hosts to allowlist for Engine APIs
*/
public record EngineRPCConfiguration(
Boolean overrideEngineRpcEnabled,
Integer engineRpcPort,
Path engineJwtKeyFile,
Boolean isEngineAuthDisabled,
JsonRPCAllowlistHostsProperty engineHostsAllowlist) {}

@ -0,0 +1,81 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.stable;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT;
import org.hyperledger.besu.cli.DefaultCommandValues;
import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import java.nio.file.Path;
import java.util.List;
import picocli.CommandLine;
/** Command line options for configuring Engine RPC on the node. */
public class EngineRPCOptions implements CLIOptions<EngineRPCConfiguration> {
/** Default constructor */
public EngineRPCOptions() {}
@CommandLine.Option(
names = {"--engine-rpc-enabled"},
description = "enable the engine api, even in the absence of merge-specific configurations.")
private final Boolean overrideEngineRpcEnabled = false;
@CommandLine.Option(
names = {"--engine-rpc-port", "--engine-rpc-http-port"},
paramLabel = DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP,
description = "Port to provide consensus client APIS on (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer engineRpcPort = DEFAULT_ENGINE_JSON_RPC_PORT;
@CommandLine.Option(
names = {"--engine-jwt-secret"},
paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP,
description = "Path to file containing shared secret key for JWT signature verification")
private final Path engineJwtKeyFile = null;
@CommandLine.Option(
names = {"--engine-jwt-disabled"},
description = "Disable authentication for Engine APIs (default: ${DEFAULT-VALUE})")
private final Boolean isEngineAuthDisabled = false;
@CommandLine.Option(
names = {"--engine-host-allowlist"},
paramLabel = "<hostname>[,<hostname>...]... or * or all",
description =
"Comma separated list of hostnames to allow for ENGINE API access (applies to both HTTP and websockets), or * to accept any host (default: ${DEFAULT-VALUE})",
defaultValue = "localhost,127.0.0.1")
private final JsonRPCAllowlistHostsProperty engineHostsAllowlist =
new JsonRPCAllowlistHostsProperty();
@Override
public EngineRPCConfiguration toDomainObject() {
return new EngineRPCConfiguration(
overrideEngineRpcEnabled,
engineRpcPort,
engineJwtKeyFile,
isEngineAuthDisabled,
engineHostsAllowlist);
}
@Override
public List<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new EngineRPCOptions());
}
}

@ -29,6 +29,7 @@ import org.slf4j.Logger;
import picocli.CommandLine; import picocli.CommandLine;
/** Handles configuration options for the GraphQL HTTP service in Besu. */ /** Handles configuration options for the GraphQL HTTP service in Besu. */
// TODO: implement CLIOptions<GraphQLConfiguration>
public class GraphQlOptions { public class GraphQlOptions {
@CommandLine.Option( @CommandLine.Option(
names = {"--graphql-http-enabled"}, names = {"--graphql-http-enabled"},

@ -52,6 +52,7 @@ import picocli.CommandLine;
* Handles configuration options for the JSON-RPC HTTP service, including validation and creation of * Handles configuration options for the JSON-RPC HTTP service, including validation and creation of
* a JSON-RPC configuration. * a JSON-RPC configuration.
*/ */
// TODO: implement CLIOption<JsonRpcConfiguration>
public class JsonRpcHttpOptions { public class JsonRpcHttpOptions {
@CommandLine.Option( @CommandLine.Option(
names = {"--rpc-http-enabled"}, names = {"--rpc-http-enabled"},
@ -265,37 +266,50 @@ public class JsonRpcHttpOptions {
/** /**
* Creates a JsonRpcConfiguration based on the provided options. * Creates a JsonRpcConfiguration based on the provided options.
* *
* @param hostsAllowlist List of hosts allowed * @return configuration populated from options or defaults
* @param defaultHostAddress Default host address
* @param timoutSec timeout in seconds
* @return A JsonRpcConfiguration instance
*/ */
public JsonRpcConfiguration jsonRpcConfiguration( public JsonRpcConfiguration jsonRpcConfiguration() {
final List<String> hostsAllowlist, final String defaultHostAddress, final Long timoutSec) {
final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault();
jsonRpcConfiguration.setEnabled(isRpcHttpEnabled); jsonRpcConfiguration.setEnabled(isRpcHttpEnabled);
jsonRpcConfiguration.setHost(
Strings.isNullOrEmpty(rpcHttpHost) ? defaultHostAddress : rpcHttpHost);
jsonRpcConfiguration.setPort(rpcHttpPort); jsonRpcConfiguration.setPort(rpcHttpPort);
jsonRpcConfiguration.setMaxActiveConnections(rpcHttpMaxConnections); jsonRpcConfiguration.setMaxActiveConnections(rpcHttpMaxConnections);
jsonRpcConfiguration.setCorsAllowedDomains(rpcHttpCorsAllowedOrigins); jsonRpcConfiguration.setCorsAllowedDomains(rpcHttpCorsAllowedOrigins);
jsonRpcConfiguration.setRpcApis(rpcHttpApis.stream().distinct().collect(Collectors.toList())); jsonRpcConfiguration.setRpcApis(rpcHttpApis.stream().distinct().collect(Collectors.toList()));
jsonRpcConfiguration.setNoAuthRpcApis( jsonRpcConfiguration.setNoAuthRpcApis(
rpcHttpApiMethodsNoAuth.stream().distinct().collect(Collectors.toList())); rpcHttpApiMethodsNoAuth.stream().distinct().collect(Collectors.toList()));
jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist);
jsonRpcConfiguration.setAuthenticationEnabled(isRpcHttpAuthenticationEnabled); jsonRpcConfiguration.setAuthenticationEnabled(isRpcHttpAuthenticationEnabled);
jsonRpcConfiguration.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile); jsonRpcConfiguration.setAuthenticationCredentialsFile(rpcHttpAuthenticationCredentialsFile);
jsonRpcConfiguration.setAuthenticationPublicKeyFile(rpcHttpAuthenticationPublicKeyFile); jsonRpcConfiguration.setAuthenticationPublicKeyFile(rpcHttpAuthenticationPublicKeyFile);
jsonRpcConfiguration.setAuthenticationAlgorithm(rpcHttpAuthenticationAlgorithm); jsonRpcConfiguration.setAuthenticationAlgorithm(rpcHttpAuthenticationAlgorithm);
jsonRpcConfiguration.setTlsConfiguration(rpcHttpTlsConfiguration()); jsonRpcConfiguration.setTlsConfiguration(rpcHttpTlsConfiguration());
jsonRpcConfiguration.setHttpTimeoutSec(timoutSec);
jsonRpcConfiguration.setMaxBatchSize(rpcHttpMaxBatchSize); jsonRpcConfiguration.setMaxBatchSize(rpcHttpMaxBatchSize);
jsonRpcConfiguration.setMaxRequestContentLength(rpcHttpMaxRequestContentLength); jsonRpcConfiguration.setMaxRequestContentLength(rpcHttpMaxRequestContentLength);
jsonRpcConfiguration.setPrettyJsonEnabled(prettyJsonEnabled); jsonRpcConfiguration.setPrettyJsonEnabled(prettyJsonEnabled);
return jsonRpcConfiguration; return jsonRpcConfiguration;
} }
/**
* Creates a JsonRpcConfiguration based on the provided options.
*
* @param hostsAllowlist List of hosts allowed
* @param defaultHostAddress Default host address
* @param timoutSec timeout in seconds
* @return A JsonRpcConfiguration instance
*/
public JsonRpcConfiguration jsonRpcConfiguration(
final List<String> hostsAllowlist, final String defaultHostAddress, final Long timoutSec) {
final JsonRpcConfiguration jsonRpcConfiguration = this.jsonRpcConfiguration();
jsonRpcConfiguration.setHost(
Strings.isNullOrEmpty(rpcHttpHost) ? defaultHostAddress : rpcHttpHost);
jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist);
;
jsonRpcConfiguration.setHttpTimeoutSec(timoutSec);
return jsonRpcConfiguration;
}
/** /**
* Checks dependencies between options. * Checks dependencies between options.
* *

@ -30,6 +30,7 @@ import java.util.Set;
import picocli.CommandLine; import picocli.CommandLine;
/** Command line options for configuring metrics. */ /** Command line options for configuring metrics. */
// TODO: implement CLIOption<MetricsConfiguration> and rename to drop the Group
public class MetricsOptionGroup { public class MetricsOptionGroup {
@CommandLine.Option( @CommandLine.Option(
names = {"--metrics-enabled"}, names = {"--metrics-enabled"},

@ -0,0 +1,238 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.stable;
import org.hyperledger.besu.cli.DefaultCommandValues;
import org.hyperledger.besu.cli.converter.PercentageConverter;
import org.hyperledger.besu.cli.converter.SubnetInfoConverter;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.ethereum.p2p.discovery.P2PDiscoveryConfiguration;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.util.NetworkUtility;
import org.hyperledger.besu.util.number.Fraction;
import org.hyperledger.besu.util.number.Percentage;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.tuweni.bytes.Bytes;
import picocli.CommandLine;
/** Command line options for configuring P2P discovery on the node. */
public class P2PDiscoveryOptions implements CLIOptions<P2PDiscoveryConfiguration> {
/** Default constructor */
public P2PDiscoveryOptions() {}
// Public IP stored to prevent having to research it each time we need it.
private InetAddress autoDiscoveredDefaultIP = null;
/** Completely disables P2P within Besu. */
@CommandLine.Option(
names = {"--p2p-enabled"},
description = "Enable P2P functionality (default: ${DEFAULT-VALUE})",
arity = "1")
public final Boolean p2pEnabled = true;
/**
* Boolean option to indicate if peers should NOT be discovered, default to false indicates that
* the peers should be discovered by default.
*/
//
// This negative option is required because of the nature of the option that is
// true when
// added on the command line. You can't do --option=false, so false is set as
// default
// and you have not to set the option at all if you want it false.
// This seems to be the only way it works with Picocli.
// Also many other software use the same negative option scheme for false
// defaults
// meaning that it's probably the right way to handle disabling options.
@CommandLine.Option(
names = {"--discovery-enabled"},
description = "Enable P2P discovery (default: ${DEFAULT-VALUE})",
arity = "1")
public final Boolean peerDiscoveryEnabled = true;
/**
* A list of bootstrap nodes can be passed and a hardcoded list will be used otherwise by the
* Runner.
*/
// NOTE: we have no control over default value here.
@CommandLine.Option(
names = {"--bootnodes"},
paramLabel = "<enode://id@host:port>",
description =
"Comma separated enode URLs for P2P discovery bootstrap. "
+ "Default is a predefined list.",
split = ",",
arity = "0..*")
public final List<String> bootNodes = null;
/** The IP the node advertises to peers for P2P communication. */
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
names = {"--p2p-host"},
paramLabel = DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP,
description = "IP address this node advertises to its peers (default: ${DEFAULT-VALUE})",
arity = "1")
public String p2pHost = autoDiscoverDefaultIP().getHostAddress();
/** The network interface address on which this node listens for P2P communication. */
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
names = {"--p2p-interface"},
paramLabel = DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP,
description =
"The network interface address on which this node listens for P2P communication (default: ${DEFAULT-VALUE})",
arity = "1")
public String p2pInterface = NetworkUtility.INADDR_ANY;
/** The port on which this node listens for P2P communication. */
@CommandLine.Option(
names = {"--p2p-port"},
paramLabel = DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP,
description = "Port on which to listen for P2P communication (default: ${DEFAULT-VALUE})",
arity = "1")
public final Integer p2pPort = EnodeURLImpl.DEFAULT_LISTENING_PORT;
/** The maximum number of peers this node can connect to. */
@CommandLine.Option(
names = {"--max-peers", "--p2p-peer-upper-bound"},
paramLabel = DefaultCommandValues.MANDATORY_INTEGER_FORMAT_HELP,
description = "Maximum P2P connections that can be established (default: ${DEFAULT-VALUE})")
public final Integer maxPeers = DefaultCommandValues.DEFAULT_MAX_PEERS;
/** Boolean option to limit the number of P2P connections initiated remotely. */
@CommandLine.Option(
names = {"--remote-connections-limit-enabled"},
description =
"Whether to limit the number of P2P connections initiated remotely. (default: ${DEFAULT-VALUE})")
public final Boolean isLimitRemoteWireConnectionsEnabled = true;
/** The maximum percentage of P2P connections that can be initiated remotely. */
@CommandLine.Option(
names = {"--remote-connections-max-percentage"},
paramLabel = DefaultCommandValues.MANDATORY_DOUBLE_FORMAT_HELP,
description =
"The maximum percentage of P2P connections that can be initiated remotely. Must be between 0 and 100 inclusive. (default: ${DEFAULT-VALUE})",
arity = "1",
converter = PercentageConverter.class)
public final Percentage maxRemoteConnectionsPercentage =
Fraction.fromFloat(DefaultCommandValues.DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED)
.toPercentage();
/** The URL to use for DNS discovery. */
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
names = {"--discovery-dns-url"},
description = "Specifies the URL to use for DNS discovery")
public String discoveryDnsUrl = null;
/** Boolean option to allow for incoming connections to be prioritized randomly. */
@CommandLine.Option(
names = {"--random-peer-priority-enabled"},
description =
"Allow for incoming connections to be prioritized randomly. This will prevent (typically small, stable) networks from forming impenetrable peer cliques. (default: ${DEFAULT-VALUE})")
public final Boolean randomPeerPriority = Boolean.FALSE;
/** A list of node IDs to ban from the P2P network. */
@CommandLine.Option(
names = {"--banned-node-ids", "--banned-node-id"},
paramLabel = DefaultCommandValues.MANDATORY_NODE_ID_FORMAT_HELP,
description = "A list of node IDs to ban from the P2P network.",
split = ",",
arity = "1..*")
void setBannedNodeIds(final List<String> values) {
try {
bannedNodeIds =
values.stream()
.filter(value -> !value.isEmpty())
.map(EnodeURLImpl::parseNodeId)
.collect(Collectors.toList());
} catch (final IllegalArgumentException e) {
throw new CommandLine.ParameterException(
new CommandLine(this), "Invalid ids supplied to '--banned-node-ids'. " + e.getMessage());
}
}
// Boolean option to set that in a PoA network the bootnodes should always be queried during
// peer table refresh. If this flag is disabled bootnodes are only sent FINDN requests on first
// startup, meaning that an offline bootnode or network outage at the client can prevent it
// discovering any peers without a restart.
@CommandLine.Option(
names = {"--poa-discovery-retry-bootnodes"},
description =
"Always use of bootnodes for discovery in PoA networks. Disabling this reverts "
+ " to the same behaviour as non-PoA networks, where neighbours are only discovered from bootnodes on first startup."
+ "(default: ${DEFAULT-VALUE})",
arity = "1")
private final Boolean poaDiscoveryRetryBootnodes = true;
private Collection<Bytes> bannedNodeIds = new ArrayList<>();
/**
* Auto-discovers the default IP of the client.
*
* @return machine loopback address
*/
// Loopback IP is used by default as this is how smokeTests require it to be
// and it's probably a good security behaviour to default only on the localhost.
public InetAddress autoDiscoverDefaultIP() {
autoDiscoveredDefaultIP =
Optional.ofNullable(autoDiscoveredDefaultIP).orElseGet(InetAddress::getLoopbackAddress);
return autoDiscoveredDefaultIP;
}
@CommandLine.Option(
names = {"--net-restrict"},
arity = "1..*",
split = ",",
converter = SubnetInfoConverter.class,
description =
"Comma-separated list of allowed IP subnets (e.g., '192.168.1.0/24,10.0.0.0/8').")
private List<SubnetUtils.SubnetInfo> allowedSubnets;
@Override
public P2PDiscoveryConfiguration toDomainObject() {
return new P2PDiscoveryConfiguration(
p2pEnabled,
peerDiscoveryEnabled,
p2pHost,
p2pInterface,
p2pPort,
maxPeers,
isLimitRemoteWireConnectionsEnabled,
maxRemoteConnectionsPercentage,
randomPeerPriority,
bannedNodeIds,
allowedSubnets,
poaDiscoveryRetryBootnodes,
bootNodes,
discoveryDnsUrl);
}
@Override
public List<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new P2PDiscoveryOptions());
}
}

@ -30,6 +30,7 @@ import org.slf4j.Logger;
import picocli.CommandLine; import picocli.CommandLine;
/** Handles configuration options for permissions in Besu. */ /** Handles configuration options for permissions in Besu. */
// TODO: implement CLIOption<PermissioningConfiguration>
public class PermissionsOptions { public class PermissionsOptions {
@CommandLine.Option( @CommandLine.Option(
names = {"--permissions-nodes-config-file-enabled"}, names = {"--permissions-nodes-config-file-enabled"},

@ -23,6 +23,7 @@ import java.util.List;
import picocli.CommandLine; import picocli.CommandLine;
/** The Metrics cli options. */ /** The Metrics cli options. */
// TODO: combine into MetricsOptionGroup, use Unstable inner class pattern (see MiningOptions)
public class MetricsCLIOptions implements CLIOptions<MetricsConfiguration.Builder> { public class MetricsCLIOptions implements CLIOptions<MetricsConfiguration.Builder> {
private static final String TIMERS_ENABLED_FLAG = "--Xmetrics-timers-enabled"; private static final String TIMERS_ENABLED_FLAG = "--Xmetrics-timers-enabled";
private static final String IDLE_TIMEOUT_FLAG = "--Xmetrics-idle-timeout"; private static final String IDLE_TIMEOUT_FLAG = "--Xmetrics-idle-timeout";

@ -12,7 +12,7 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package org.hyperledger.besu.cli.options.stable; package org.hyperledger.besu.cli.options.unstable;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.hyperledger.besu.cli.DefaultCommandValues.DEFAULT_KEYSTORE_TYPE; import static org.hyperledger.besu.cli.DefaultCommandValues.DEFAULT_KEYSTORE_TYPE;

@ -15,11 +15,11 @@
package org.hyperledger.besu.cli.subcommands.storage; package org.hyperledger.besu.cli.subcommands.storage;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.hyperledger.besu.cli.options.stable.DataStorageOptions.BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD; import static org.hyperledger.besu.cli.options.DataStorageOptions.BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD;
import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE;
import org.hyperledger.besu.cli.options.stable.DataStorageOptions; import org.hyperledger.besu.cli.options.DataStorageOptions;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;

@ -20,7 +20,10 @@ import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter; import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.BesuCommand; import org.hyperledger.besu.cli.BesuCommand;
import org.hyperledger.besu.cli.options.stable.P2PDiscoveryOptions;
import org.hyperledger.besu.cli.options.unstable.RPCOptions;
import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.p2p.discovery.P2PDiscoveryConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.BesuPluginContextImpl;
@ -53,7 +56,6 @@ public class BesuCommandModule {
new BesuPluginContextImpl(), new BesuPluginContextImpl(),
System.getenv(), System.getenv(),
commandLogger); commandLogger);
besuCommand.toCommandLine();
return besuCommand; return besuCommand;
} }
@ -63,6 +65,18 @@ public class BesuCommandModule {
return provideFrom.metricsConfiguration(); return provideFrom.metricsConfiguration();
} }
@Provides
@Singleton
RPCOptions provideRPCOptions() {
return RPCOptions.create();
}
@Provides
@Singleton
P2PDiscoveryConfiguration provideP2PDiscoveryConfiguration() {
return new P2PDiscoveryOptions().toDomainObject();
}
@Provides @Provides
@Named("besuCommandLogger") @Named("besuCommandLogger")
@Singleton @Singleton

@ -34,9 +34,9 @@ import org.hyperledger.besu.chainexport.RlpBlockExporter;
import org.hyperledger.besu.chainimport.JsonBlockImporter; import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.options.DataStorageOptions;
import org.hyperledger.besu.cli.options.MiningOptions; import org.hyperledger.besu.cli.options.MiningOptions;
import org.hyperledger.besu.cli.options.TransactionPoolOptions; import org.hyperledger.besu.cli.options.TransactionPoolOptions;
import org.hyperledger.besu.cli.options.stable.DataStorageOptions;
import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.cli.options.stable.EthstatsOptions;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions; import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions; import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;

@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT;
import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest; import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest;
import org.hyperledger.besu.cli.options.DataStorageOptions;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;

@ -17,6 +17,8 @@ package org.hyperledger.besu.config;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
/** The Merge config options. */ /** The Merge config options. */
// TODO: naming this with Options as the suffix is misleading, it should be MergeConfig - doesn't
// use picocli
public class MergeConfigOptions { public class MergeConfigOptions {
private static final AtomicBoolean mergeEnabled = new AtomicBoolean(false); private static final AtomicBoolean mergeEnabled = new AtomicBoolean(false);

@ -0,0 +1,39 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.p2p.discovery;
import org.hyperledger.besu.util.number.Percentage;
import java.util.Collection;
import java.util.List;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.tuweni.bytes.Bytes;
public record P2PDiscoveryConfiguration(
Boolean p2pEnabled,
Boolean peerDiscoveryEnabled,
String p2pHost,
String p2pInterface,
Integer p2pPort,
Integer maxPeers,
Boolean isLimitRemoteWireConnectionsEnabled,
Percentage maxRemoteConnectionsPercentage,
Boolean randomPeerPriority,
Collection<Bytes> bannedNodeIds,
List<SubnetUtils.SubnetInfo> allowedSubnets,
Boolean poaDiscoveryRetryBootnodes,
List<String> bootNodes,
String discoveryDnsUrl) {}
Loading…
Cancel
Save