diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9fdae30a99..c72331b84e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -7,7 +7,7 @@ on: jobs: spotless: - runs-on: [besu-research-ubuntu-16] + runs-on: [besu,Linux,self-hosted,X64,nodocker] if: ${{ github.actor != 'dependabot[bot]' }} steps: - name: Checkout Repo @@ -21,7 +21,7 @@ jobs: - name: spotless run: ./gradlew --no-daemon --parallel clean spotlessCheck javadoc_17: - runs-on: [besu-research-ubuntu-8] + runs-on: [besu,Linux,self-hosted,X64,nodocker] if: ${{ github.actor != 'dependabot[bot]' }} steps: - name: Checkout Repo diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 100be39e0d..0e170cfb28 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,7 +24,7 @@ on: jobs: analyze: name: Analyze - runs-on: [besu-research-ubuntu-16] + runs-on: [besu,Linux,self-hosted,X64,nodocker] permissions: actions: read contents: read diff --git a/.github/workflows/dco-merge-group.yml b/.github/workflows/dco-merge-group.yml index fee29b6c5d..f93170b1c2 100644 --- a/.github/workflows/dco-merge-group.yml +++ b/.github/workflows/dco-merge-group.yml @@ -4,7 +4,7 @@ on: jobs: dco: - runs-on: [besu-research-ubuntu-8] + runs-on: [besu,Linux,self-hosted,nodocker] if: ${{ github.actor != 'dependabot[bot]' }} steps: - - run: echo "This DCO job runs on merge_queue event and doesn't check PR contents" + - run: echo "This DCO job runs on merge_queue event and doesn't check PR contents" \ No newline at end of file diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml index 5fa9931c77..341e1d3877 100644 --- a/.github/workflows/dco.yml +++ b/.github/workflows/dco.yml @@ -5,7 +5,7 @@ on: jobs: dco: - runs-on: [besu-research-ubuntu-8] + runs-on: [besu,Linux,self-hosted,nodocker] if: ${{ github.actor != 'dependabot[bot]' }} steps: - run: echo "This DCO job runs on pull_request event and workflow_dispatch" @@ -17,4 +17,4 @@ jobs: - name: DCO Check uses: tim-actions/dco@v1.1.0 with: - commits: ${{ steps.get-pr-commits.outputs.commits }} + commits: ${{ steps.get-pr-commits.outputs.commits }} \ No newline at end of file diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 2be77e8c2e..bb0feddd1e 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: validation: name: "Gradle Wrapper Validation" - runs-on: [besu-research-ubuntu-8] + runs-on: [besu,Linux,self-hosted,nodocker] steps: - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/pr-checklist-on-open.yml b/.github/workflows/pr-checklist-on-open.yml index 3a4d4342c5..d89748a943 100644 --- a/.github/workflows/pr-checklist-on-open.yml +++ b/.github/workflows/pr-checklist-on-open.yml @@ -6,7 +6,7 @@ on: jobs: checklist: name: "add checklist as a comment on newly opened PRs" - runs-on: [besu-research-ubuntu-8] + runs-on: [besu,Linux,self-hosted,nodocker] steps: - uses: actions/github-script@v5 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c9b232820..36ea3ab50f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: types: released jobs: dockerPromoteX64: - runs-on: [besu-research-ubuntu-16] + runs-on: [besu,Linux,self-hosted,nodocker] steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/.github/workflows/repolinter.yml b/.github/workflows/repolinter.yml index e1c61cadea..39b0d6cab3 100644 --- a/.github/workflows/repolinter.yml +++ b/.github/workflows/repolinter.yml @@ -15,7 +15,7 @@ on: jobs: build: - runs-on: [besu-research-ubuntu-16] + runs-on: [besu,Linux,self-hosted,X64,docker] container: ghcr.io/todogroup/repolinter:v0.10.1 steps: - name: Checkout Code diff --git a/CHANGELOG.md b/CHANGELOG.md index 429ae790c0..6339b818d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,21 +2,8 @@ ## 23.7.3 -### Breaking Changes -- Removed support for Kotti network (ETC) [#5816](https://github.com/hyperledger/besu/pull/5816) -- Layered transaction pool implementation is now stable and enabled by default, so the following changes to experimental options have been done [#5772](https://github.com/hyperledger/besu): - - `--Xlayered-tx-pool` is gone, to select the implementation use the new `--tx-pool` option with values `layered` (default) or `legacy` - - `--Xlayered-tx-pool-layer-max-capacity`, `--Xlayered-tx-pool-max-prioritized` and `--Xlayered-tx-pool-max-future-by-sender` just drop the `X` and keep the same behavior - ### Additions and Improvements -- Add access to an immutable world view to start/end transaction hooks in the tracing API[#5836](https://github.com/hyperledger/besu/pull/5836) -- Layered transaction pool implementation is now stable and enabled by default. If you want still to use the legacy implementation, use `--tx-pool=legacy` [#5772](https://github.com/hyperledger/besu) -- Tune G1GC to reduce Besu memory footprint, and new `besu-untuned` start scripts to run without any specific G1GC flags [#5879](https://github.com/hyperledger/besu/pull/5879) -- Update Holešky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890) - -### Bug Fixes -- do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830) -- fix duplicate key errors in EthScheduler-Transactions [#5857](https://github.com/hyperledger/besu/pull/5857) +- Update Holesky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890) ### Download Links diff --git a/README.md b/README.md index 38eb3e7725..98560c66ed 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ If you have any questions, queries or comments, [Besu channel on Hyperledger Dis ## Besu Users -To install the Besu binary, follow [these instructions](https://besu.hyperledger.org/public-networks/get-started/install/binary-distribution). +To install the Besu binary, follow [these instructions](https://besu.hyperledger.org/HowTo/Get-Started/Install-Binaries/). ## Besu Developers 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 2538a1d705..e0330170b7 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -46,6 +46,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.config.NetworkName; +import org.hyperledger.besu.cli.converter.FractionConverter; import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.converter.PercentageConverter; import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty; @@ -58,7 +59,6 @@ import org.hyperledger.besu.cli.options.stable.EthstatsOptions; import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption; import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions; -import org.hyperledger.besu.cli.options.stable.TransactionPoolOptions; import org.hyperledger.besu.cli.options.unstable.ChainPruningOptions; import org.hyperledger.besu.cli.options.unstable.DnsOptions; import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions; @@ -73,6 +73,7 @@ import org.hyperledger.besu.cli.options.unstable.PkiBlockCreationOptions; import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions; import org.hyperledger.besu.cli.options.unstable.RPCOptions; import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions; +import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions; import org.hyperledger.besu.cli.presynctasks.PreSynchronizationTaskRunner; import org.hyperledger.besu.cli.presynctasks.PrivateDatabaseMigrationPreSyncTask; import org.hyperledger.besu.cli.subcommands.PasswordSubCommand; @@ -126,7 +127,6 @@ import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.mainnet.FrontierTargetingGasLimitCalculator; import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration; @@ -280,9 +280,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { final SynchronizerOptions unstableSynchronizerOptions = SynchronizerOptions.create(); final EthProtocolOptions unstableEthProtocolOptions = EthProtocolOptions.create(); final MetricsCLIOptions unstableMetricsCLIOptions = MetricsCLIOptions.create(); - final org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions - unstableTransactionPoolOptions = - org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions.create(); + final TransactionPoolOptions unstableTransactionPoolOptions = TransactionPoolOptions.create(); private final DnsOptions unstableDnsOptions = DnsOptions.create(); private final MiningOptions unstableMiningOptions = MiningOptions.create(); private final NatOptions unstableNatOptions = NatOptions.create(); @@ -300,10 +298,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { NodePrivateKeyFileOption.create(); private final LoggingLevelOption loggingLevelOption = LoggingLevelOption.create(); - @CommandLine.ArgGroup(validate = false, heading = "@|bold Tx Pool Common Options|@%n") - final org.hyperledger.besu.cli.options.stable.TransactionPoolOptions - stableTransactionPoolOptions = TransactionPoolOptions.create(); - private final RunnerBuilder runnerBuilder; private final BesuController.Builder controllerBuilderFactory; private final BesuPluginContextImpl besuPluginContext; @@ -460,8 +454,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "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(); + private final Integer maxRemoteConnectionsPercentage = + Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED) + .toPercentage() + .getValue(); @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @CommandLine.Option( @@ -1115,6 +1111,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable { arity = "1") private final Wei minTransactionGasPrice = DEFAULT_MIN_TRANSACTION_GAS_PRICE; + @Option( + names = {"--rpc-tx-feecap"}, + description = + "Maximum transaction fees (in Wei) accepted for transaction submitted through RPC (default: ${DEFAULT-VALUE})", + arity = "1") + private final Wei txFeeCap = DEFAULT_RPC_TX_FEE_CAP; + @Option( names = {"--min-block-occupancy-ratio"}, description = "Minimum occupancy ratio for a mined block (default: ${DEFAULT-VALUE})", @@ -1206,6 +1209,75 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "Sets target gas limit per block. If set, each block's gas limit will approach this setting over time if the current gas limit is different.") private final Long targetGasLimit = null; + // Tx Pool Option Group + @CommandLine.ArgGroup(validate = false, heading = "@|bold Tx Pool Options|@%n") + TxPoolOptionGroup txPoolOptionGroup = new TxPoolOptionGroup(); + + static class TxPoolOptionGroup { + @CommandLine.Option( + names = {"--tx-pool-disable-locals"}, + paramLabel = "", + description = + "Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS; + + @CommandLine.Option( + names = {"--tx-pool-enable-save-restore"}, + paramLabel = "", + description = + "Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE; + + @CommandLine.Option( + names = {"--tx-pool-limit-by-account-percentage"}, + paramLabel = "", + converter = FractionConverter.class, + description = + "Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})", + arity = "1") + private Float txPoolLimitByAccountPercentage = + TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; + + @CommandLine.Option( + names = {"--tx-pool-save-file"}, + paramLabel = "", + description = + "If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)", + arity = "1") + private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE; + + @Option( + names = {"--tx-pool-max-size"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer txPoolMaxSize = + TransactionPoolConfiguration.DEFAULT_MAX_PENDING_TRANSACTIONS; + + @Option( + names = {"--tx-pool-retention-hours"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + description = + "Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer pendingTxRetentionPeriod = + TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS; + + @Option( + names = {"--tx-pool-price-bump"}, + paramLabel = MANDATORY_INTEGER_FORMAT_HELP, + converter = PercentageConverter.class, + description = + "Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})", + arity = "1") + private final Integer priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP.getValue(); + } + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @Option( names = {"--key-value-storage"}, @@ -1834,15 +1906,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable { validateRpcOptionsParams(); validateChainDataPruningParams(); validatePostMergeCheckpointBlockRequirements(); - validateTransactionPoolOptions(); p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine); pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine); } - private void validateTransactionPoolOptions() { - stableTransactionPoolOptions.validate(commandLine); - } - private void validateRequiredOptions() { commandLine .getCommandSpec() @@ -2920,14 +2987,28 @@ public class BesuCommand implements DefaultCommandValues, Runnable { } private TransactionPoolConfiguration buildTransactionPoolConfiguration() { - final var stableTxPoolOption = stableTransactionPoolOptions.toDomainObject(); - return ImmutableTransactionPoolConfiguration.builder() - .from(stableTxPoolOption) - .unstable(unstableTransactionPoolOptions.toDomainObject()) - .saveFile((dataPath.resolve(stableTxPoolOption.getSaveFile().getPath()).toFile())) + return unstableTransactionPoolOptions + .toDomainObject() + .enableSaveRestore(txPoolOptionGroup.saveRestoreEnabled) + .disableLocalTransactions(txPoolOptionGroup.disableLocalTxs) + .txPoolLimitByAccountPercentage(txPoolOptionGroup.txPoolLimitByAccountPercentage) + .txPoolMaxSize(txPoolOptionGroup.txPoolMaxSize) + .pendingTxRetentionPeriod(txPoolOptionGroup.pendingTxRetentionPeriod) + .priceBump(Percentage.fromInt(txPoolOptionGroup.priceBump)) + .txFeeCap(txFeeCap) + .saveFile(dataPath.resolve(txPoolOptionGroup.saveFile.getPath()).toFile()) .build(); } + /** + * Return the file where to save txpool content if the relative option is enabled. + * + * @return the save file + */ + public File getSaveFile() { + return txPoolOptionGroup.saveFile; + } + private boolean isPruningEnabled() { return pruningEnabled; } @@ -3408,8 +3489,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { getActualGenesisConfigOptions().getTerminalTotalDifficulty().isPresent()); } - /** Set ignorable segments in RocksDB Storage Provider plugin. */ - public void setIgnorableStorageSegments() { + private void setIgnorableStorageSegments() { if (!unstableChainPruningOptions.getChainDataPruningEnabled()) { rocksDBPlugin.addIgnorableSegmentIdentifier(KeyValueSegmentIdentifier.CHAIN_PRUNER_STATE); } @@ -3532,7 +3612,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable { builder.setHighSpecEnabled(); } - builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation()); + if (buildTransactionPoolConfiguration().getLayeredTxPoolEnabled()) { + builder.setLayeredTxPoolEnabled(); + } return builder.build(); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java index 5bd1d84a29..2cd374a2f5 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.cli; import org.hyperledger.besu.BesuInfo; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.util.log.FramedLogMessage; import org.hyperledger.besu.util.platform.PlatformDetector; @@ -48,7 +47,7 @@ public class ConfigurationOverviewBuilder { private Collection engineApis; private String engineJwtFilePath; private boolean isHighSpec = false; - private TransactionPoolConfiguration.Implementation txPoolImplementation; + private boolean isLayeredTxPool = false; private Map environment; /** @@ -168,14 +167,12 @@ public class ConfigurationOverviewBuilder { } /** - * Sets the txpool implementation in use. + * Sets experimental layered txpool enabled. * - * @param implementation the txpool implementation * @return the builder */ - public ConfigurationOverviewBuilder setTxPoolImplementation( - final TransactionPoolConfiguration.Implementation implementation) { - txPoolImplementation = implementation; + public ConfigurationOverviewBuilder setLayeredTxPoolEnabled() { + isLayeredTxPool = true; return this; } @@ -254,7 +251,9 @@ public class ConfigurationOverviewBuilder { lines.add("Experimental high spec configuration enabled"); } - lines.add("Using " + txPoolImplementation + " transaction pool implementation"); + if (isLayeredTxPool) { + lines.add("Experimental layered transaction pool configuration enabled"); + } lines.add(""); lines.add("Host:"); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java index 8b83726832..887e612041 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java @@ -16,6 +16,7 @@ package org.hyperledger.besu.cli; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; import org.hyperledger.besu.nat.NatMethod; @@ -60,6 +61,9 @@ public interface DefaultCommandValues { String MANDATORY_NODE_ID_FORMAT_HELP = ""; /** The constant DEFAULT_MIN_TRANSACTION_GAS_PRICE. */ Wei DEFAULT_MIN_TRANSACTION_GAS_PRICE = Wei.of(1000); + /** The constant DEFAULT_RPC_TX_FEE_CAP. */ + Wei DEFAULT_RPC_TX_FEE_CAP = TransactionPoolConfiguration.DEFAULT_RPC_TX_FEE_CAP; + /** The constant DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO. */ Double DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO = 0.8; /** The constant DEFAULT_EXTRA_DATA. */ diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java index 6638ddfa44..a83ef68aae 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java @@ -38,6 +38,8 @@ public enum NetworkName { EXPERIMENTAL_EIPS("/experimental.json", BigInteger.valueOf(2023), false), /** Classic network name. */ CLASSIC("/classic.json", BigInteger.valueOf(1)), + /** Kotti network name. */ + KOTTI("/kotti.json", BigInteger.valueOf(6)), /** Mordor network name. */ MORDOR("/mordor.json", BigInteger.valueOf(7)); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/DurationMillisConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/DurationMillisConverter.java deleted file mode 100644 index bfaffa8826..0000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/DurationMillisConverter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.cli.converter; - -import org.hyperledger.besu.cli.converter.exception.DurationConversionException; - -import java.time.Duration; - -import picocli.CommandLine; - -/** The Duration (milliseconds) Cli type converter. */ -public class DurationMillisConverter - implements CommandLine.ITypeConverter, TypeFormatter { - - @Override - public Duration convert(final String value) throws DurationConversionException { - try { - final long millis = Long.parseLong(value); - if (millis < 0) { - throw new DurationConversionException(millis); - } - return Duration.ofMillis(Long.parseLong(value)); - } catch (NullPointerException | IllegalArgumentException e) { - throw new DurationConversionException(value); - } - } - - @Override - public String format(final Duration value) { - return Long.toString(value.toMillis()); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java index 64edf7cd9c..969a6be8e9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java @@ -20,12 +20,12 @@ import org.hyperledger.besu.util.number.Fraction; import picocli.CommandLine; /** The Fraction converter to convert floats in CLI. */ -public class FractionConverter implements CommandLine.ITypeConverter { +public class FractionConverter implements CommandLine.ITypeConverter { @Override - public Fraction convert(final String value) throws FractionConversionException { + public Float convert(final String value) throws FractionConversionException { try { - return Fraction.fromString(value); + return Fraction.fromString(value).getValue(); } catch (final NullPointerException | IllegalArgumentException e) { throw new FractionConversionException(value); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java index 410ec83a21..23a2d94d33 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java @@ -20,12 +20,12 @@ import org.hyperledger.besu.util.number.Percentage; import picocli.CommandLine; /** The Percentage Cli type converter. */ -public class PercentageConverter implements CommandLine.ITypeConverter { +public class PercentageConverter implements CommandLine.ITypeConverter { @Override - public Percentage convert(final String value) throws PercentageConversionException { + public Integer convert(final String value) throws PercentageConversionException { try { - return Percentage.fromString(value); + return Percentage.fromString(value).getValue(); } catch (NullPointerException | IllegalArgumentException e) { throw new PercentageConversionException(value); } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/DurationConversionException.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/DurationConversionException.java deleted file mode 100644 index cd56d06188..0000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/exception/DurationConversionException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.cli.converter.exception; - -import static java.lang.String.format; - -/** The custom Duration conversion exception. */ -public final class DurationConversionException extends Exception { - - /** - * Instantiates a new Duration conversion exception for malformed value. - * - * @param value the value - */ - public DurationConversionException(final String value) { - super(format("'%s' is not a long", value)); - } - - /** - * Instantiates a new Duration conversion exception for negative value. - * - * @param value the millis - */ - public DurationConversionException(final long value) { - super(format("negative value '%d' is not allowed", value)); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java b/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java index 003ad8846e..73161742f9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java @@ -16,11 +16,6 @@ package org.hyperledger.besu.cli.options; import static com.google.common.base.Preconditions.checkArgument; -import org.hyperledger.besu.datatypes.Wei; - -import java.lang.invoke.MethodType; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Iterator; import com.google.common.base.Splitter; @@ -101,44 +96,4 @@ public class OptionParser { public static String format(final UInt256 value) { return value.toBigInteger().toString(10); } - - /** - * Format Wei to string. - * - * @param value the value - * @return the string - */ - public static String format(final Wei value) { - return format(value.toUInt256()); - } - - /** - * Format any object to string. This implementation tries to find an existing format method, in - * this class, that matches the type of the passed object, and if not found just invoke, to string - * on the passed object - * - * @param value the object - * @return the string - */ - public static String format(final Object value) { - Method formatMethod; - try { - formatMethod = OptionParser.class.getMethod("format", value.getClass()); - } catch (NoSuchMethodException e) { - try { - // maybe a primitive version of the method exists - formatMethod = - OptionParser.class.getMethod( - "format", MethodType.methodType(value.getClass()).unwrap().returnType()); - } catch (NoSuchMethodException ex) { - return value.toString(); - } - } - - try { - return (String) formatMethod.invoke(null, value); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/TransactionPoolOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/TransactionPoolOptions.java deleted file mode 100644 index 6353618d24..0000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/TransactionPoolOptions.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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.cli.options.stable; - -import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_DOUBLE_FORMAT_HELP; -import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_INTEGER_FORMAT_HELP; -import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_LONG_FORMAT_HELP; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LAYERED; -import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LEGACY; - -import org.hyperledger.besu.cli.converter.FractionConverter; -import org.hyperledger.besu.cli.converter.PercentageConverter; -import org.hyperledger.besu.cli.options.CLIOptions; -import org.hyperledger.besu.cli.util.CommandLineUtils; -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import org.hyperledger.besu.util.number.Fraction; -import org.hyperledger.besu.util.number.Percentage; - -import java.io.File; -import java.util.List; - -import picocli.CommandLine; - -/** The Transaction pool Cli stable options. */ -public class TransactionPoolOptions implements CLIOptions { - private static final String TX_POOL_IMPLEMENTATION = "--tx-pool"; - private static final String TX_POOL_DISABLE_LOCALS = "--tx-pool-disable-locals"; - private static final String TX_POOL_ENABLE_SAVE_RESTORE = "--tx-pool-enable-save-restore"; - private static final String TX_POOL_SAVE_FILE = "--tx-pool-save-file"; - private static final String TX_POOL_PRICE_BUMP = "--tx-pool-price-bump"; - private static final String RPC_TX_FEECAP = "--rpc-tx-feecap"; - private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG = - "--strict-tx-replay-protection-enabled"; - - @CommandLine.Option( - names = {TX_POOL_IMPLEMENTATION}, - paramLabel = "", - description = "The Transaction Pool implementation to use(default: ${DEFAULT-VALUE})", - arity = "0..1") - private TransactionPoolConfiguration.Implementation txPoolImplementation = LAYERED; - - @CommandLine.Option( - names = {TX_POOL_DISABLE_LOCALS}, - paramLabel = "", - description = - "Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})", - fallbackValue = "true", - arity = "0..1") - private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS; - - @CommandLine.Option( - names = {TX_POOL_ENABLE_SAVE_RESTORE}, - paramLabel = "", - description = - "Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})", - fallbackValue = "true", - arity = "0..1") - private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE; - - @CommandLine.Option( - names = {TX_POOL_SAVE_FILE}, - paramLabel = "", - description = - "If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)", - arity = "1") - private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE; - - @CommandLine.Option( - names = {TX_POOL_PRICE_BUMP}, - paramLabel = "", - converter = PercentageConverter.class, - description = - "Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})", - arity = "1") - private Percentage priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP; - - @CommandLine.Option( - names = {RPC_TX_FEECAP}, - description = - "Maximum transaction fees (in Wei) accepted for transaction submitted through RPC (default: ${DEFAULT-VALUE})", - arity = "1") - private Wei txFeeCap = TransactionPoolConfiguration.DEFAULT_RPC_TX_FEE_CAP; - - @CommandLine.Option( - names = {STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG}, - paramLabel = "", - description = - "Require transactions submitted via JSON-RPC to use replay protection in accordance with EIP-155 (default: ${DEFAULT-VALUE})", - fallbackValue = "true", - arity = "0..1") - private Boolean strictTxReplayProtectionEnabled = false; - - @CommandLine.ArgGroup( - validate = false, - heading = "@|bold Tx Pool Layered Implementation Options|@%n") - private final Layered layeredOptions = new Layered(); - - static class Layered { - private static final String TX_POOL_LAYER_MAX_CAPACITY = "--tx-pool-layer-max-capacity"; - private static final String TX_POOL_MAX_PRIORITIZED = "--tx-pool-max-prioritized"; - private static final String TX_POOL_MAX_FUTURE_BY_SENDER = "--tx-pool-max-future-by-sender"; - - @CommandLine.Option( - names = {TX_POOL_LAYER_MAX_CAPACITY}, - paramLabel = MANDATORY_LONG_FORMAT_HELP, - description = - "Max amount of memory space, in bytes, that any layer within the transaction pool could occupy (default: ${DEFAULT-VALUE})", - arity = "1") - Long txPoolLayerMaxCapacity = - TransactionPoolConfiguration.DEFAULT_PENDING_TRANSACTIONS_LAYER_MAX_CAPACITY_BYTES; - - @CommandLine.Option( - names = {TX_POOL_MAX_PRIORITIZED}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Max number of pending transactions that are prioritized and thus kept sorted (default: ${DEFAULT-VALUE})", - arity = "1") - Integer txPoolMaxPrioritized = - TransactionPoolConfiguration.DEFAULT_MAX_PRIORITIZED_TRANSACTIONS; - - @CommandLine.Option( - names = {TX_POOL_MAX_FUTURE_BY_SENDER}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Max number of future pending transactions allowed for a single sender (default: ${DEFAULT-VALUE})", - arity = "1") - Integer txPoolMaxFutureBySender = TransactionPoolConfiguration.DEFAULT_MAX_FUTURE_BY_SENDER; - } - - @CommandLine.ArgGroup( - validate = false, - heading = "@|bold Tx Pool Legacy Implementation Options|@%n") - private final Legacy legacyOptions = new Legacy(); - - static class Legacy { - private static final String TX_POOL_RETENTION_HOURS = "--tx-pool-retention-hours"; - private static final String TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE = - "--tx-pool-limit-by-account-percentage"; - private static final String TX_POOL_MAX_SIZE = "--tx-pool-max-size"; - - @CommandLine.Option( - names = {TX_POOL_RETENTION_HOURS}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})", - arity = "1") - Integer pendingTxRetentionPeriod = TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS; - - @CommandLine.Option( - names = {TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE}, - paramLabel = MANDATORY_DOUBLE_FORMAT_HELP, - converter = FractionConverter.class, - description = - "Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})", - arity = "1") - Fraction txPoolLimitByAccountPercentage = - TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE; - - @CommandLine.Option( - names = {TX_POOL_MAX_SIZE}, - paramLabel = MANDATORY_INTEGER_FORMAT_HELP, - description = - "Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})", - arity = "1") - Integer txPoolMaxSize = TransactionPoolConfiguration.DEFAULT_MAX_PENDING_TRANSACTIONS; - } - - private TransactionPoolOptions() {} - - /** - * Create transaction pool options. - * - * @return the transaction pool options - */ - public static TransactionPoolOptions create() { - return new TransactionPoolOptions(); - } - - /** - * Create Transaction Pool Options from Transaction Pool Configuration. - * - * @param config the Transaction Pool Configuration - * @return the transaction pool options - */ - public static TransactionPoolOptions fromConfig(final TransactionPoolConfiguration config) { - final TransactionPoolOptions options = TransactionPoolOptions.create(); - options.txPoolImplementation = config.getTxPoolImplementation(); - options.saveRestoreEnabled = config.getEnableSaveRestore(); - options.disableLocalTxs = config.getDisableLocalTransactions(); - options.priceBump = config.getPriceBump(); - options.txFeeCap = config.getTxFeeCap(); - options.saveFile = config.getSaveFile(); - options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled(); - options.layeredOptions.txPoolLayerMaxCapacity = - config.getPendingTransactionsLayerMaxCapacityBytes(); - options.layeredOptions.txPoolMaxPrioritized = config.getMaxPrioritizedTransactions(); - options.layeredOptions.txPoolMaxFutureBySender = config.getMaxFutureBySender(); - options.legacyOptions.txPoolLimitByAccountPercentage = - config.getTxPoolLimitByAccountPercentage(); - options.legacyOptions.txPoolMaxSize = config.getTxPoolMaxSize(); - options.legacyOptions.pendingTxRetentionPeriod = config.getPendingTxRetentionPeriod(); - - return options; - } - - /** - * Validate that there are no inconsistencies in the specified options. For example that the - * options are valid for the selected implementation. - * - * @param commandLine the full commandLine to check all the options specified by the user - */ - public void validate(final CommandLine commandLine) { - CommandLineUtils.failIfOptionDoesntMeetRequirement( - commandLine, - "Could not use legacy transaction pool options with layered implementation", - !txPoolImplementation.equals(LAYERED), - CommandLineUtils.getCLIOptionNames(Legacy.class)); - - CommandLineUtils.failIfOptionDoesntMeetRequirement( - commandLine, - "Could not use layered transaction pool options with legacy implementation", - !txPoolImplementation.equals(LEGACY), - CommandLineUtils.getCLIOptionNames(Layered.class)); - } - - @Override - public TransactionPoolConfiguration toDomainObject() { - return ImmutableTransactionPoolConfiguration.builder() - .txPoolImplementation(txPoolImplementation) - .enableSaveRestore(saveRestoreEnabled) - .disableLocalTransactions(disableLocalTxs) - .priceBump(priceBump) - .txFeeCap(txFeeCap) - .saveFile(saveFile) - .strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled) - .pendingTransactionsLayerMaxCapacityBytes(layeredOptions.txPoolLayerMaxCapacity) - .maxPrioritizedTransactions(layeredOptions.txPoolMaxPrioritized) - .maxFutureBySender(layeredOptions.txPoolMaxFutureBySender) - .txPoolLimitByAccountPercentage(legacyOptions.txPoolLimitByAccountPercentage) - .txPoolMaxSize(legacyOptions.txPoolMaxSize) - .pendingTxRetentionPeriod(legacyOptions.pendingTxRetentionPeriod) - .build(); - } - - @Override - public List getCLIOptions() { - return CommandLineUtils.getCLIOptions(this, new TransactionPoolOptions()); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java index cb7994b947..e199966c25 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java @@ -14,25 +14,50 @@ */ package org.hyperledger.besu.cli.options.unstable; -import org.hyperledger.besu.cli.converter.DurationMillisConverter; import org.hyperledger.besu.cli.options.CLIOptions; -import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.cli.options.OptionParser; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import java.time.Duration; +import java.util.Arrays; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import picocli.CommandLine; -/** The Transaction pool Cli unstable options. */ -public class TransactionPoolOptions implements CLIOptions { +/** The Transaction pool Cli options. */ +public class TransactionPoolOptions + implements CLIOptions { + private static final Logger LOG = LoggerFactory.getLogger(TransactionPoolOptions.class); + private static final String TX_MESSAGE_KEEP_ALIVE_SEC_FLAG = "--Xincoming-tx-messages-keep-alive-seconds"; private static final String ETH65_TX_ANNOUNCED_BUFFERING_PERIOD_FLAG = "--Xeth65-tx-announced-buffering-period-milliseconds"; + private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG = + "--strict-tx-replay-protection-enabled"; + + private static final String LAYERED_TX_POOL_ENABLED_FLAG = "--Xlayered-tx-pool"; + private static final String LAYERED_TX_POOL_LAYER_MAX_CAPACITY = + "--Xlayered-tx-pool-layer-max-capacity"; + private static final String LAYERED_TX_POOL_MAX_PRIORITIZED = + "--Xlayered-tx-pool-max-prioritized"; + private static final String LAYERED_TX_POOL_MAX_FUTURE_BY_SENDER = + "--Xlayered-tx-pool-max-future-by-sender"; + + @CommandLine.Option( + names = {STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG}, + paramLabel = "", + description = + "Require transactions submitted via JSON-RPC to use replay protection in accordance with EIP-155 (default: ${DEFAULT-VALUE})", + fallbackValue = "true", + arity = "0..1") + private Boolean strictTxReplayProtectionEnabled = false; + @CommandLine.Option( names = {TX_MESSAGE_KEEP_ALIVE_SEC_FLAG}, paramLabel = "", @@ -41,18 +66,56 @@ public class TransactionPoolOptions implements CLIOptions