diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfb4ebd3e..41aea176de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Added isLabelsObserved to LabelledGauge in plugin-api. Default implementation returns false. ### Breaking Changes +- Removed Retesteth rpc service and commands [#7833](https://github.com/hyperledger/besu/pull/7783) ### Upcoming Breaking Changes @@ -12,8 +13,10 @@ - Create and publish Besu BOM (Bill of Materials) [#7615](https://github.com/hyperledger/besu/pull/7615) - Update Java dependencies [#7786](https://github.com/hyperledger/besu/pull/7786) - Add a method to get all the transaction in the pool, to the `TransactionPoolService`, to easily access the transaction pool content from plugins [#7813](https://github.com/hyperledger/besu/pull/7813) +- Add a method to check if a metric category is enabled to the plugin API [#7832](https://github.com/hyperledger/besu/pull/7832) ### Bug fixes +- Fix registering new metric categories from plugins [#7825](https://github.com/hyperledger/besu/pull/7825) ## 24.10.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c2d6c57d25..c13ea67852 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Welcome to the Besu repository! The following links are a set of guidelines for Having the following accounts is necessary for contributing code/issues to Besu. * If you want to contribute code, you can make a [github account here](https://github.com). * If you want to raise an issue, do so [in the issues tab](https://github.com/hyperledger/besu/issues). -* To ask questions or chat with us, join our [Discord](https://discord.gg/hyperledger) +* To ask questions or chat with us, join our [Discord](https://discord.com/invite/hyperledger) * To edit pages in our wiki, you'll need a [Linux Foundation (LF) account]. ### Useful contributing links diff --git a/DCO.md b/DCO.md index 4bf56cb80a..48227cadcd 100644 --- a/DCO.md +++ b/DCO.md @@ -5,4 +5,4 @@ As per section 13.a of the [Hyperledger Charter](https://www.hyperledger.org/abo The sign off needs to be using your legal name, not a pseudonym. Git has a built-in mechanism to allow this with the `-s` or `--signoff` argument to `git commit` command, providing your `user.name` and `user.email` have been setup correctly. -If you have any questions, you can reach us on Besu chat; first, [join the Discord server](https://discord.gg/hyperledger/) then [join the Besu channel](https://discord.com/channels/905194001349627914/938504958909747250). +If you have any questions, you can reach us on Besu chat; first, [join the Discord server](https://discord.com/invite/hyperledger) then [join the Besu channel](https://discord.com/channels/905194001349627914/938504958909747250). diff --git a/MAINTAINERS.md b/MAINTAINERS.md index ae6720632a..afb82b6fc5 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -84,7 +84,7 @@ The following steps must occur for a contributor to be "upgraded" as a maintaine - The proposed maintainer accepts the nomination and expresses a willingness to be a long-term (more than 6 month) committer by adding a comment in the proposal PR. - The PR will be communicated in all appropriate communication channels - including at least [besu-contributors channel on Discord](https://discord.gg/hyperledger), + including at least [besu-contributors channel on Discord](https://discord.com/invite/hyperledger), the [mailing list](https://lists.hyperledger.org/g/besu) and any maintainer/community call. - Approval by at least 3 current maintainers within two weeks of the proposal or diff --git a/README.md b/README.md index 7139df8580..8f5f51a726 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Documentation](https://img.shields.io/github/actions/workflow/status/hyperledger/besu-docs/publish-main-docs.yml?branch=main&label=docs)](https://github.com/hyperledger/besu-docs/actions/workflows/publish-main-docs.yml) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3174/badge)](https://bestpractices.coreinfrastructure.org/projects/3174) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/hyperledger/besu/blob/main/LICENSE) - [![Discord](https://img.shields.io/discord/905194001349627914?logo=Hyperledger&style=plastic)](https://discord.gg/hyperledger) + [![Discord](https://img.shields.io/discord/905194001349627914?logo=Hyperledger&style=plastic)](https://discord.com/invite/hyperledger) [![Twitter Follow](https://img.shields.io/twitter/follow/HyperledgerBesu)](https://twitter.com/HyperledgerBesu) [Download](https://github.com/hyperledger/besu/releases) @@ -67,5 +67,5 @@ and YourKit YouMonitor. [Besu Issues]: https://github.com/hyperledger/besu/issues [Besu User Documentation]: https://besu.hyperledger.org -[Besu channel on Discord]: https://discord.gg/hyperledger +[Besu channel on Discord]: https://discord.com/invite/hyperledger [Contributing Guidelines]: CONTRIBUTING.md diff --git a/SUPPORT.md b/SUPPORT.md index 9e4a7b7b42..97715857cb 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -20,5 +20,5 @@ Having Github, Discord, and Linux Foundation accounts is necessary for obtaining [Besu User Documentation]: https://besu.hyperledger.org -[Besu channel on Discord]: https://discord.gg/hyperledger +[Besu channel on Discord]: https://discord.com/invite/hyperledger [Contributing Guidelines]: CONTRIBUTING.md diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 42c0df73c7..036a1e0019 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -57,6 +57,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.MetricCategoryRegistryImpl; import org.hyperledger.besu.metrics.MetricsSystemModule; import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.BesuConfiguration; @@ -406,9 +407,18 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner { } } + @Module + public static class ThreadBesuNodeRunnerModule { + @Provides + @Singleton + public ThreadBesuNodeRunner provideThreadBesuNodeRunner() { + return new ThreadBesuNodeRunner(); + } + } + @Module @SuppressWarnings("CloseableProvides") - static class BesuControllerModule { + public static class BesuControllerModule { @Provides @Singleton public SynchronizerConfiguration provideSynchronizationConfiguration() { @@ -579,7 +589,16 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner { } @Module - static class MockBesuCommandModule { + public static class ObservableMetricsSystemModule { + @Provides + @Singleton + public ObservableMetricsSystem provideObservableMetricsSystem() { + return new NoOpMetricsSystem(); + } + } + + @Module + public static class MockBesuCommandModule { @Provides BesuCommand provideBesuCommand(final BesuPluginContextImpl pluginContext) { @@ -610,6 +629,8 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner { modules = { ThreadBesuNodeRunner.BesuControllerModule.class, ThreadBesuNodeRunner.MockBesuCommandModule.class, + ThreadBesuNodeRunner.ObservableMetricsSystemModule.class, + ThreadBesuNodeRunnerModule.class, BonsaiCachedMerkleTrieLoaderModule.class, MetricsSystemModule.class, ThreadBesuNodeRunner.BesuNodeProviderModule.class, @@ -625,5 +646,9 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner { RpcEndpointServiceImpl rpcEndpointService(); BlockchainServiceImpl blockchainService(); + + ObservableMetricsSystem getObservableMetricsSystem(); + + ThreadBesuNodeRunner getThreadBesuNodeRunner(); } } diff --git a/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestMetricsPlugin.java b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestMetricsPlugin.java new file mode 100644 index 0000000000..7e1ac2ccde --- /dev/null +++ b/acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/tests/acceptance/plugins/TestMetricsPlugin.java @@ -0,0 +1,76 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import org.hyperledger.besu.plugin.BesuContext; +import org.hyperledger.besu.plugin.BesuPlugin; +import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.hyperledger.besu.plugin.services.metrics.MetricCategory; +import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; + +import java.util.Locale; +import java.util.Optional; + +import com.google.auto.service.AutoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@AutoService(BesuPlugin.class) +public class TestMetricsPlugin implements BesuPlugin { + private static final Logger LOG = LoggerFactory.getLogger(TestMetricsPlugin.class); + private BesuContext besuContext; + + @Override + public void register(final BesuContext context) { + LOG.info("Registering TestMetricsPlugin"); + besuContext = context; + context + .getService(MetricCategoryRegistry.class) + .orElseThrow() + .addMetricCategory(TestMetricCategory.TEST_METRIC_CATEGORY); + } + + @Override + public void start() { + LOG.info("Starting TestMetricsPlugin"); + besuContext + .getService(MetricsSystem.class) + .orElseThrow() + .createGauge( + TestMetricCategory.TEST_METRIC_CATEGORY, + "test_metric", + "Returns 1 on succes", + () -> 1.0); + } + + @Override + public void stop() { + LOG.info("Stopping TestMetricsPlugin"); + } + + public enum TestMetricCategory implements MetricCategory { + TEST_METRIC_CATEGORY; + + @Override + public String getName() { + return name().toLowerCase(Locale.ROOT); + } + + @Override + public Optional getApplicationPrefix() { + return Optional.of("plugin_test_"); + } + } +} diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index fdc7735452..b6c388172e 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -31,6 +31,7 @@ dependencies { api 'org.slf4j:slf4j-api' implementation project(':crypto:algorithms') + implementation project(':ethereum:eth') testImplementation project(':acceptance-tests:dsl') testImplementation project(':acceptance-tests:test-plugins') @@ -42,6 +43,7 @@ dependencies { testImplementation project(':ethereum:api') testImplementation project(':ethereum:core') testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') + testImplementation project(':ethereum:eth') testImplementation project(':ethereum:p2p') testImplementation project(':ethereum:permissioning') testImplementation project(':ethereum:rlp') @@ -78,6 +80,8 @@ dependencies { testImplementation 'org.web3j:besu' testImplementation 'org.web3j:core' testImplementation 'org.wiremock:wiremock' + testImplementation 'com.google.dagger:dagger' + testAnnotationProcessor 'com.google.dagger:dagger-compiler' testImplementation project(path: ':acceptance-tests:tests:shanghai') } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/MetricsPluginTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/MetricsPluginTest.java new file mode 100644 index 0000000000..7559200720 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/MetricsPluginTest.java @@ -0,0 +1,73 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.plugins; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.tests.acceptance.plugins.TestMetricsPlugin.TestMetricCategory.TEST_METRIC_CATEGORY; + +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.List; +import java.util.Set; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class MetricsPluginTest extends AcceptanceTestBase { + private BesuNode node; + private MetricsConfiguration metricsConfiguration; + + @BeforeEach + public void setUp() throws Exception { + metricsConfiguration = + MetricsConfiguration.builder() + .enabled(true) + .port(0) + .metricCategories(Set.of(TEST_METRIC_CATEGORY)) + .build(); + node = + besu.create( + new BesuNodeConfigurationBuilder() + .name("node1") + .plugins(List.of("testPlugins")) + .metricsConfiguration(metricsConfiguration) + .build()); + + cluster.start(node); + } + + @Test + public void metricCategoryAdded() throws IOException, InterruptedException { + final var httpClient = HttpClient.newHttpClient(); + final var req = HttpRequest.newBuilder(URI.create(node.metricsHttpUrl().get())).build(); + final var resp = httpClient.send(req, HttpResponse.BodyHandlers.ofLines()); + assertThat(resp.statusCode()).isEqualTo(200); + final var foundMetric = + resp.body() + .filter( + line -> line.startsWith(TEST_METRIC_CATEGORY.getApplicationPrefix().orElseThrow())) + .findFirst() + .orElseThrow(); + assertThat(foundMetric).endsWith("1.0"); + } +} 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 886e3d6838..8a01236725 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -37,7 +37,6 @@ 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.config.ProfilesCompletionCandidates; -import org.hyperledger.besu.cli.converter.MetricCategoryConverter; import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty; import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler; import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler; @@ -75,7 +74,6 @@ import org.hyperledger.besu.cli.presynctasks.PreSynchronizationTaskRunner; import org.hyperledger.besu.cli.presynctasks.PrivateDatabaseMigrationPreSyncTask; import org.hyperledger.besu.cli.subcommands.PasswordSubCommand; import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand; -import org.hyperledger.besu.cli.subcommands.RetestethSubCommand; import org.hyperledger.besu.cli.subcommands.TxParseSubCommand; import org.hyperledger.besu.cli.subcommands.ValidateConfigSubCommand; import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand; @@ -170,7 +168,6 @@ import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService; import org.hyperledger.besu.plugin.services.TransactionSelectionService; import org.hyperledger.besu.plugin.services.TransactionSimulationService; import org.hyperledger.besu.plugin.services.exception.StorageException; -import org.hyperledger.besu.plugin.services.metrics.MetricCategory; import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; import org.hyperledger.besu.plugin.services.p2p.P2PService; import org.hyperledger.besu.plugin.services.rlp.RlpConverterService; @@ -332,7 +329,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { private final Map environment; private final MetricCategoryRegistryImpl metricCategoryRegistry = new MetricCategoryRegistryImpl(); - private final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter(); private final PreSynchronizationTaskRunner preSynchronizationTaskRunner = new PreSynchronizationTaskRunner(); @@ -1108,7 +1104,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { PublicKeySubCommand.COMMAND_NAME, new PublicKeySubCommand(commandLine.getOut())); commandLine.addSubcommand( PasswordSubCommand.COMMAND_NAME, new PasswordSubCommand(commandLine.getOut())); - commandLine.addSubcommand(RetestethSubCommand.COMMAND_NAME, new RetestethSubCommand()); commandLine.addSubcommand( RLPSubCommand.COMMAND_NAME, new RLPSubCommand(commandLine.getOut(), in)); commandLine.addSubcommand( @@ -1136,10 +1131,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { commandLine.registerConverter(Hash.class, Hash::fromHexString); commandLine.registerConverter(Optional.class, Optional::of); commandLine.registerConverter(Double.class, Double::parseDouble); - - metricCategoryConverter.addCategories(BesuMetricCategory.class); - metricCategoryConverter.addCategories(StandardMetricCategory.class); - commandLine.registerConverter(MetricCategory.class, metricCategoryConverter); } private void handleStableOptions() { @@ -1174,6 +1165,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable { besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); besuPluginContext.addService(SecurityModuleService.class, securityModuleService); besuPluginContext.addService(StorageService.class, storageService); + + metricCategoryRegistry.addCategories(BesuMetricCategory.class); + metricCategoryRegistry.addCategories(StandardMetricCategory.class); besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry); besuPluginContext.addService(PermissioningService.class, permissioningService); besuPluginContext.addService(PrivacyPluginService.class, privacyPluginService); @@ -1191,10 +1185,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable { rocksDBPlugin.register(besuPluginContext); new InMemoryStoragePlugin().register(besuPluginContext); - metricCategoryRegistry - .getMetricCategories() - .forEach(metricCategoryConverter::addRegistryCategory); - // register default security module securityModuleService.register( DEFAULT_SECURITY_MODULE, Suppliers.memoize(this::defaultSecurityModule)); @@ -1891,6 +1881,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "--metrics-push-interval", "--metrics-push-prometheus-job")); + metricsOptions.setMetricCategoryRegistry(metricCategoryRegistry); + + metricsOptions.validate(commandLine); + final MetricsConfiguration.Builder metricsConfigurationBuilder = metricsOptions.toDomainObject(); metricsConfigurationBuilder @@ -1903,7 +1897,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable { ? p2PDiscoveryOptions.autoDiscoverDefaultIP().getHostAddress() : metricsOptions.getMetricsPushHost()) .hostsAllowlist(hostsAllowlist); - return metricsConfigurationBuilder.build(); + final var metricsConfiguration = metricsConfigurationBuilder.build(); + metricCategoryRegistry.setMetricsConfiguration(metricsConfiguration); + return metricsConfiguration; } private PrivacyParameters privacyParameters() { diff --git a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java b/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java deleted file mode 100644 index 339da86b2d..0000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/converter/MetricCategoryConverter.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.converter; - -import org.hyperledger.besu.plugin.services.metrics.MetricCategory; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import com.google.common.annotations.VisibleForTesting; -import picocli.CommandLine; - -/** The Metric category converter for CLI options. */ -public class MetricCategoryConverter implements CommandLine.ITypeConverter { - - private final Map metricCategories = new HashMap<>(); - - /** Default Constructor. */ - public MetricCategoryConverter() {} - - @Override - public MetricCategory convert(final String value) { - final MetricCategory category = metricCategories.get(value); - if (category == null) { - throw new IllegalArgumentException("Unknown category: " + value); - } - return category; - } - - /** - * Add Metrics categories. - * - * @param the type parameter - * @param categoryEnum the category enum - */ - public & MetricCategory> void addCategories(final Class categoryEnum) { - EnumSet.allOf(categoryEnum) - .forEach(category -> metricCategories.put(category.name(), category)); - } - - /** - * Add registry category. - * - * @param metricCategory the metric category - */ - public void addRegistryCategory(final MetricCategory metricCategory) { - metricCategories.put(metricCategory.getName().toUpperCase(Locale.ROOT), metricCategory); - } - - /** - * Gets metric categories. - * - * @return the metric categories - */ - @VisibleForTesting - Map getMetricCategories() { - return metricCategories; - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptions.java index 4906cf538e..beba20e29b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/MetricsOptions.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.cli.options.stable; +import static com.google.common.base.Preconditions.checkState; +import static java.util.stream.Collectors.toUnmodifiableSet; import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP; import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_INTEGER_FORMAT_HELP; import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP; @@ -24,6 +26,7 @@ import static org.hyperledger.besu.metrics.prometheus.MetricsConfiguration.DEFAU import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.metrics.MetricCategoryRegistryImpl; import org.hyperledger.besu.metrics.MetricsProtocol; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; @@ -36,6 +39,7 @@ import picocli.CommandLine; /** Command line options for configuring metrics. */ // TODO: implement CLIOption public class MetricsOptions implements CLIOptions { + private MetricCategoryRegistryImpl metricCategoryRegistry; /** * Returns a MetricsConfiguration.Builder because fields are often overridden from other domains, @@ -77,7 +81,10 @@ public class MetricsOptions implements CLIOptions metricsOptions.metricsHost = config.getHost(); metricsOptions.metricsPort = config.getPort(); metricsOptions.metricsProtocol = config.getProtocol(); - metricsOptions.metricCategories = config.getMetricCategories(); + metricsOptions.metricCategories = + config.getMetricCategories().stream() + .map(MetricCategory::getName) + .collect(toUnmodifiableSet()); metricsOptions.metricsPrometheusJob = config.getPrometheusJob(); metricsOptions.isMetricsPushEnabled = config.isPushEnabled(); metricsOptions.metricsPushHost = config.getPushHost(); @@ -126,7 +133,8 @@ public class MetricsOptions implements CLIOptions arity = "1..*", description = "Comma separated list of categories to track metrics for (default: ${DEFAULT-VALUE})") - private Set metricCategories = DEFAULT_METRIC_CATEGORIES; + private Set metricCategories = + DEFAULT_METRIC_CATEGORIES.stream().map(MetricCategory::getName).collect(toUnmodifiableSet()); @CommandLine.Option( names = {"--metrics-push-enabled"}, @@ -216,7 +224,13 @@ public class MetricsOptions implements CLIOptions * @return the metric categories */ public Set getMetricCategories() { - return metricCategories; + checkState( + metricCategoryRegistry != null, "Set metricCategoryRegistry before calling this method"); + + final var list = + metricCategories.stream().map(metricCategoryRegistry::getMetricCategory).toList(); + + return Set.copyOf(list); } /** @@ -264,6 +278,33 @@ public class MetricsOptions implements CLIOptions return metricsPrometheusJob; } + /** + * Perform final validation after all the options, and the metric category registry, have been set + * + * @param commandLine the command line + */ + public void validate(final CommandLine commandLine) { + checkState( + metricCategoryRegistry != null, "Set metricCategoryRegistry before calling this method"); + final var unknownCategories = + metricCategories.stream() + .filter(category -> !metricCategoryRegistry.containsMetricCategory(category)) + .toList(); + if (!unknownCategories.isEmpty()) { + throw new CommandLine.ParameterException( + commandLine, "--metrics-categories contains unknown categories: " + unknownCategories); + } + } + + /** + * Set the metric category registry in order to support verification and conversion + * + * @param metricCategoryRegistry the metric category registry + */ + public void setMetricCategoryRegistry(final MetricCategoryRegistryImpl metricCategoryRegistry) { + this.metricCategoryRegistry = metricCategoryRegistry; + } + @CommandLine.ArgGroup(validate = false) private final MetricsOptions.Unstable unstableOptions = new MetricsOptions.Unstable(); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/RetestethSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/RetestethSubCommand.java deleted file mode 100644 index 67af49c400..0000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/RetestethSubCommand.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.subcommands; - -import static org.hyperledger.besu.cli.subcommands.RetestethSubCommand.COMMAND_NAME; - -import org.hyperledger.besu.BesuInfo; -import org.hyperledger.besu.cli.DefaultCommandValues; -import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty; -import org.hyperledger.besu.cli.options.stable.LoggingLevelOption; -import org.hyperledger.besu.cli.util.VersionProvider; -import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.retesteth.RetestethConfiguration; -import org.hyperledger.besu.ethereum.retesteth.RetestethService; -import org.hyperledger.besu.util.LogConfigurator; - -import java.net.InetAddress; -import java.nio.file.Path; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Mixin; -import picocli.CommandLine.Option; - -/** Subcommand to run a Retesteth compatible server for reference tests. */ -@Command( - name = COMMAND_NAME, - description = "Run a Retesteth compatible server for reference tests.", - mixinStandardHelpOptions = true, - versionProvider = VersionProvider.class) -@SuppressWarnings("unused") -public class RetestethSubCommand implements Runnable { - - private static final Logger LOG = LoggerFactory.getLogger(RetestethSubCommand.class); - - /** The constant COMMAND_NAME. */ - public static final String COMMAND_NAME = "retesteth"; - - /** - * Using a distinct port for retesteth will result in less testing collisions and accidental RPC - * calls. This is 0xba5e in hex, a hex speak play on the english translation of - * "Besu." - */ - public static final int RETESTETH_PORT = 47710; - - @Option( - names = {"--data-path"}, - paramLabel = DefaultCommandValues.MANDATORY_PATH_FORMAT_HELP, - description = "The path to Besu data directory (default: ${DEFAULT-VALUE})") - private final Path dataPath = DefaultCommandValues.getDefaultBesuDataPath(this); - - @Mixin private LoggingLevelOption loggingLevelOption; - - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. - @Option( - names = {"--rpc-http-host"}, - paramLabel = DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP, - description = "Host for Retesteth JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private String rpcHttpHost = autoDiscoverDefaultIP().getHostAddress(); - - @Option( - names = {"--rpc-http-port"}, - paramLabel = DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP, - description = "Port for Retesteth JSON-RPC HTTP to listen on (default: ${DEFAULT-VALUE})", - arity = "1") - private final Integer rpcHttpPort = RETESTETH_PORT; - - @Option( - names = {"--host-allowlist", "--host-whitelist"}, - paramLabel = "[,...]... or * or all", - description = - "Comma separated list of hostnames to allow for RPC access, or * to accept any host (default: ${DEFAULT-VALUE})", - defaultValue = "localhost,127.0.0.1") - private final JsonRPCAllowlistHostsProperty hostsAllowlist = new JsonRPCAllowlistHostsProperty(); - - private InetAddress autoDiscoveredDefaultIP; - - /** Default Constructor. */ - public RetestethSubCommand() {} - - // 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() { - - if (autoDiscoveredDefaultIP != null) { - return autoDiscoveredDefaultIP; - } - - autoDiscoveredDefaultIP = InetAddress.getLoopbackAddress(); - - return autoDiscoveredDefaultIP; - } - - private void prepareLogging() { - // set log level per CLI flags - final String logLevel = loggingLevelOption.getLogLevel(); - if (logLevel != null) { - System.out.println("Setting logging level to " + logLevel); - LogConfigurator.setLevel("", logLevel); - } - } - - @Override - public void run() { - prepareLogging(); - - final RetestethConfiguration retestethConfiguration = new RetestethConfiguration(dataPath); - final JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault(); - jsonRpcConfiguration.setHost(rpcHttpHost); - jsonRpcConfiguration.setPort(rpcHttpPort); - jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist); - - final RetestethService retestethService = - new RetestethService(BesuInfo.version(), retestethConfiguration, jsonRpcConfiguration); - - Runtime.getRuntime() - .addShutdownHook( - new Thread( - () -> { - try { - retestethService.close(); - LogConfigurator.shutdown(); - } catch (final Exception e) { - LOG.error("Failed to stop Besu Retesteth"); - } - })); - retestethService.start(); - try { - Thread.sleep(Long.MAX_VALUE); // Is there a better way? - } catch (final InterruptedException e) { - // e.printStackTrace(); - } - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java index b4ada60549..77bf60b034 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java @@ -132,7 +132,6 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder { genesisConfigOptions, forksSchedule, nodeKey, - privacyParameters, isRevertReasonEnabled, evmConfiguration, miningParameters, diff --git a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java index e0fbed608a..dbd2c5904a 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MainnetBesuControllerBuilder.java @@ -31,6 +31,8 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import java.util.Optional; + /** The Mainnet besu controller builder. */ public class MainnetBesuControllerBuilder extends BesuControllerBuilder { @@ -95,10 +97,10 @@ public class MainnetBesuControllerBuilder extends BesuControllerBuilder { protected ProtocolSchedule createProtocolSchedule() { return MainnetProtocolSchedule.fromConfig( genesisConfigOptions, - privacyParameters, - isRevertReasonEnabled, - evmConfiguration, - miningParameters, + Optional.of(privacyParameters), + Optional.of(isRevertReasonEnabled), + Optional.of(evmConfiguration), + super.miningParameters, badBlockManager, isParallelTxProcessingEnabled, metricsSystem); diff --git a/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java index 0adbda23b7..6d9a5410c4 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java @@ -31,7 +31,7 @@ public class BesuConfigurationImpl implements BesuConfiguration { private DataStorageConfiguration dataStorageConfiguration; // defaults - private MiningParameters miningParameters = MiningParameters.newDefault(); + private MiningParameters miningParameters; private Optional rpcHttpHost = Optional.of("http://localhost"); private Optional rpcHttpPort = Optional.of(8545); diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java index 7b1a4bc7d2..bc52cb60be 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java @@ -17,9 +17,10 @@ package org.hyperledger.besu.chainimport; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; +import org.hyperledger.besu.components.BesuCommandModule; import org.hyperledger.besu.components.BesuComponent; +import org.hyperledger.besu.components.BesuPluginContextModule; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.controller.BesuController; @@ -36,12 +37,16 @@ import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitV import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.core.components.MiningParametersModule; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; +import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.metrics.MetricsSystemModule; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.testutil.TestClock; @@ -52,9 +57,13 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; +import javax.inject.Singleton; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.io.Resources; +import dagger.Component; +import dagger.Module; +import dagger.Provides; import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -465,7 +474,28 @@ public abstract class JsonBlockImporterTest { .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) - .besuComponent(mock(BesuComponent.class)) + .besuComponent(DaggerJsonBlockImporterTest_JsonBlockImportComponent.builder().build()) .build(); } + + @Module + public static class JsonBlockImporterModule { + + @Provides + BonsaiCachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule() { + return new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()); + } + } + + @Singleton + @Component( + modules = { + BesuCommandModule.class, + MiningParametersModule.class, + MetricsSystemModule.class, + JsonBlockImporterModule.class, + BesuPluginContextModule.class, + BlobCacheModule.class + }) + interface JsonBlockImportComponent extends BesuComponent {} } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 019e8d83cd..cf3c40860d 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -40,6 +40,7 @@ import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import org.hyperledger.besu.BesuInfo; import org.hyperledger.besu.cli.config.EthNetworkConfig; @@ -99,7 +100,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import picocli.CommandLine; @@ -566,7 +566,7 @@ public class BesuCommandTest extends CommandTestAbstract { parseCommand("--genesis-file", genesisFile.toString(), "--network", "mainnet"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) @@ -578,7 +578,7 @@ public class BesuCommandTest extends CommandTestAbstract { final String nonExistentGenesis = "non-existent-genesis.json"; parseCommand("--genesis-file", nonExistentGenesis); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).startsWith("Unable to load genesis file"); @@ -1177,7 +1177,7 @@ public class BesuCommandTest extends CommandTestAbstract { parseCommand( "--remote-connections-limit-enabled", "--remote-connections-max-percentage", "invalid"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1190,7 +1190,7 @@ public class BesuCommandTest extends CommandTestAbstract { parseCommand( "--remote-connections-limit-enabled", "--remote-connections-max-percentage", "150"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1225,7 +1225,7 @@ public class BesuCommandTest extends CommandTestAbstract { @Test public void syncMode_invalid() { parseCommand("--sync-mode", "bogus"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) @@ -1275,7 +1275,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void helpShouldDisplayFastSyncOptions() { parseCommand("--help"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).contains("--fast-sync-min-peers"); // whitelist is now a hidden option @@ -1335,7 +1335,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void parsesInvalidFastSyncMinPeersOptionWrongFormatShouldFail() { parseCommand("--sync-mode", "FAST", "--fast-sync-min-peers", "ten"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains("Invalid value for option '--fast-sync-min-peers': 'ten' is not an int"); @@ -1358,7 +1358,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void netRestrictInvalidShouldFail() { final String subnet = "127.0.0.1/abc"; parseCommand("--net-restrict", subnet); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandErrorOutput.toString(UTF_8)) .contains("Invalid value for option '--net-restrict'"); } @@ -1382,7 +1382,7 @@ public class BesuCommandTest extends CommandTestAbstract { @Test public void ethStatsContactOptionCannotBeUsedWithoutEthStatsServerProvided() { parseCommand("--ethstats-contact", "besu-updated"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1435,7 +1435,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void parsesInvalidWhenFullSyncAndBonsaiLimitTrieLogsExplicitlyTrue() { parseCommand("--sync-mode=FULL", "--bonsai-limit-trie-logs-enabled=true"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1467,7 +1467,7 @@ public class BesuCommandTest extends CommandTestAbstract { parseCommand("--data-storage-format", "BONSAI", "--bonsai-maximum-back-layers-to-load", "ten"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1501,7 +1501,7 @@ public class BesuCommandTest extends CommandTestAbstract { @Test public void dnsUpdateEnabledOptionCannotBeUsedWithoutDnsEnabled() { parseCommand("--Xdns-update-enabled", "true"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( @@ -1720,6 +1720,17 @@ public class BesuCommandTest extends CommandTestAbstract { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } + @Test + public void metricsUnknownCategoryRaiseError() { + parseCommand("--metrics-enabled", "--metrics-category", "UNKNOWN_CATEGORY"); + + verifyNoInteractions(mockRunnerBuilder); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)) + .startsWith("--metrics-categories contains unknown categories: [UNKNOWN_CATEGORY]"); + } + @Test public void metricsPushEnabledPropertyMustBeUsed() { parseCommand("--metrics-push-enabled"); @@ -1799,7 +1810,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void metricsAndMetricsPushMustNotBeUsedTogether() { parseCommand("--metrics-enabled", "--metrics-push-enabled"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) @@ -2023,7 +2034,7 @@ public class BesuCommandTest extends CommandTestAbstract { public void fullCLIOptionsShown() { parseCommand("--help"); - Mockito.verifyNoInteractions(mockRunnerBuilder); + verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).contains("--config-file"); assertThat(commandOutput.toString(UTF_8)).contains("--data-path"); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/converter/MetricCategoryConverterTest.java b/besu/src/test/java/org/hyperledger/besu/cli/converter/MetricCategoryConverterTest.java deleted file mode 100644 index 8c78b7fecc..0000000000 --- a/besu/src/test/java/org/hyperledger/besu/cli/converter/MetricCategoryConverterTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.cli.converter; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.Mockito.when; - -import org.hyperledger.besu.plugin.services.metrics.MetricCategory; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class MetricCategoryConverterTest { - - private MetricCategoryConverter metricCategoryConverter; - - @Mock MetricCategory metricCategory; - - @BeforeEach - public void setUp() { - metricCategoryConverter = new MetricCategoryConverter(); - } - - @Test - public void convertShouldFailIfValueNotRegistered() { - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> metricCategoryConverter.convert("notRegistered")); - } - - @Test - public void addRegistryCategoryShouldUppercaseInputValues() { - when(metricCategory.getName()).thenReturn("testcat"); - metricCategoryConverter.addRegistryCategory(metricCategory); - when(metricCategory.getName()).thenReturn("tesTCat2"); - metricCategoryConverter.addRegistryCategory(metricCategory); - - final boolean containsLowercase = - metricCategoryConverter.getMetricCategories().keySet().stream() - .anyMatch(testString -> testString.chars().anyMatch(Character::isLowerCase)); - - assertThat(containsLowercase).isFalse(); - assertThat(metricCategoryConverter.getMetricCategories().size()).isEqualTo(2); - assertThat(metricCategoryConverter.getMetricCategories().keySet()) - .containsExactlyInAnyOrder("TESTCAT", "TESTCAT2"); - } -} diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/MetricsOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/MetricsOptionsTest.java index 992dcc437d..cd541759ad 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/MetricsOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/MetricsOptionsTest.java @@ -15,14 +15,26 @@ package org.hyperledger.besu.cli.options; import org.hyperledger.besu.cli.options.stable.MetricsOptions; +import org.hyperledger.besu.metrics.BesuMetricCategory; +import org.hyperledger.besu.metrics.MetricCategoryRegistryImpl; +import org.hyperledger.besu.metrics.StandardMetricCategory; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class MetricsOptionsTest extends AbstractCLIOptionsTest { + private MetricCategoryRegistryImpl categoryRegistry; + + @BeforeEach + public void setUp() { + categoryRegistry = new MetricCategoryRegistryImpl(); + categoryRegistry.addCategories(BesuMetricCategory.class); + categoryRegistry.addCategories(StandardMetricCategory.class); + } @Override protected MetricsConfiguration.Builder createDefaultDomainObject() { @@ -39,11 +51,18 @@ public class MetricsOptionsTest @Override protected MetricsOptions optionsFromDomainObject( final MetricsConfiguration.Builder domainObject) { - return MetricsOptions.fromConfiguration(domainObject.build()); + final var options = MetricsOptions.fromConfiguration(domainObject.build()); + options.setMetricCategoryRegistry(categoryRegistry); + return options; } @Override protected MetricsOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) { return besuCommand.getMetricsOptions(); } + + @Override + protected String[] getNonOptionFields() { + return new String[] {"metricCategoryRegistry"}; + } } diff --git a/config/build.gradle b/config/build.gradle index a78b9a7105..e269ce51fc 100644 --- a/config/build.gradle +++ b/config/build.gradle @@ -36,11 +36,13 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' + implementation 'com.google.dagger:dagger' implementation 'info.picocli:picocli' implementation 'io.tmio:tuweni-bytes' implementation 'io.tmio:tuweni-units' implementation "org.immutables:value-annotations" annotationProcessor "org.immutables:value" + annotationProcessor 'com.google.dagger:dagger-compiler' testImplementation project(':testutil') diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java index cd19755638..551a8c3f44 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java @@ -110,7 +110,7 @@ public class CliqueProtocolSchedule { return new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), specAdapters, privacyParameters, isRevertReasonEnabled, diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleBuilder.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleBuilder.java index 311bf30fae..0df63452b3 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleBuilder.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BaseBftProtocolScheduleBuilder.java @@ -38,6 +38,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.Function; /** Defines the protocol behaviours for a blockchain using a BFT consensus mechanism. */ @@ -90,7 +91,7 @@ public abstract class BaseBftProtocolScheduleBuilder { final ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), specAdapters, privacyParameters, isRevertReasonEnabled, diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/CombinedProtocolScheduleFactoryTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/CombinedProtocolScheduleFactoryTest.java index 02689d52af..659337bdd2 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/CombinedProtocolScheduleFactoryTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/CombinedProtocolScheduleFactoryTest.java @@ -172,7 +172,7 @@ public class CombinedProtocolScheduleFactoryTest { final ProtocolScheduleBuilder protocolScheduleBuilder = new ProtocolScheduleBuilder( genesisConfigOptions, - BigInteger.ONE, + Optional.of(BigInteger.ONE), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/consensus/ibft/build.gradle b/consensus/ibft/build.gradle index da6304c4e5..e95c866143 100644 --- a/consensus/ibft/build.gradle +++ b/consensus/ibft/build.gradle @@ -76,4 +76,6 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' testImplementation 'org.mockito:mockito-junit-jupiter' + testImplementation 'com.google.dagger:dagger' + testAnnotationProcessor 'com.google.dagger:dagger-compiler' } diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java index e5551ff3f3..a5510ea80a 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java @@ -22,7 +22,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.hyperledger.besu.config.BftConfigOptions; -import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.JsonGenesisConfigOptions; import org.hyperledger.besu.config.JsonQbftConfigOptions; import org.hyperledger.besu.config.JsonUtil; @@ -43,28 +42,36 @@ import org.hyperledger.besu.ethereum.core.MilestoneStreamingProtocolSchedule; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.Util; +import org.hyperledger.besu.ethereum.core.components.EthereumCoreComponent; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.math.BigInteger; -import java.util.Collection; import java.util.List; +import javax.inject.Singleton; +import dagger.Component; +import dagger.Module; +import dagger.Provides; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class IbftProtocolScheduleTest { - private final BftExtraDataCodec bftExtraDataCodec = mock(BftExtraDataCodec.class); - private final BftExtraData bftExtraData = mock(BftExtraData.class); - private final NodeKey proposerNodeKey = NodeKeyUtils.generate(); - private final Address proposerAddress = Util.publicKeyToAddress(proposerNodeKey.getPublicKey()); - private final List
validators = singletonList(proposerAddress); + + private ProtocolContext protocolContext; + private List
validators; + private NodeKey proposerNodeKey; + private TestEthCoreComponent component; @BeforeEach public void setup() { - when(bftExtraDataCodec.decode(any())).thenReturn(bftExtraData); - when(bftExtraData.getValidators()).thenReturn(validators); + TestEthCoreComponent component = + DaggerIbftProtocolScheduleTest_TestEthCoreComponent.builder().build(); + this.component = component; + this.protocolContext = component.protocolContext(); + this.validators = component.validators(); + this.proposerNodeKey = component.nodeKey(); } @Test @@ -81,24 +88,41 @@ public class IbftProtocolScheduleTest { .buildHeader(); final BftProtocolSchedule schedule = - createProtocolSchedule( - JsonGenesisConfigOptions.fromJsonObject(JsonUtil.createEmptyObjectNode()), - List.of( - new ForkSpec<>(0, JsonQbftConfigOptions.DEFAULT), - new ForkSpec<>(1, arbitraryTransition), - new ForkSpec<>(2, JsonQbftConfigOptions.DEFAULT))); + createProtocolSchedule(component.bftExtraDataCodec(), arbitraryTransition); assertThat(new MilestoneStreamingProtocolSchedule(schedule).streamMilestoneBlocks().count()) .isEqualTo(3); - assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 0)).isTrue(); - assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 1)).isTrue(); - assertThat(validateHeader(schedule, validators, parentHeader, blockHeader, 2)).isTrue(); + assertThat(validateHeader(schedule, parentHeader, blockHeader, 0)).isTrue(); + assertThat(validateHeader(schedule, parentHeader, blockHeader, 1)).isTrue(); + assertThat(validateHeader(schedule, parentHeader, blockHeader, 2)).isTrue(); + } + + private boolean validateHeader( + final BftProtocolSchedule schedule, + final BlockHeader parentHeader, + final BlockHeader blockHeader, + final int block) { + return schedule + .getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp()) + .getBlockHeaderValidator() + .validateHeader( + blockHeader, parentHeader, this.protocolContext, HeaderValidationMode.LIGHT); } private BftProtocolSchedule createProtocolSchedule( - final GenesisConfigOptions genesisConfig, final List> forks) { + final BftExtraDataCodec bftExtraDataCodec, + final MutableBftConfigOptions arbitraryTransition) { + + var genesisConfig = JsonGenesisConfigOptions.fromJsonObject(JsonUtil.createEmptyObjectNode()); + ForksSchedule forkSched = + new ForksSchedule<>( + List.of( + new ForkSpec<>(0, JsonQbftConfigOptions.DEFAULT), + new ForkSpec<>(1, arbitraryTransition), + new ForkSpec<>(2, JsonQbftConfigOptions.DEFAULT))); + return IbftProtocolScheduleBuilder.create( genesisConfig, - new ForksSchedule<>(forks), + forkSched, PrivacyParameters.DEFAULT, false, bftExtraDataCodec, @@ -109,24 +133,66 @@ public class IbftProtocolScheduleTest { new NoOpMetricsSystem()); } - private boolean validateHeader( - final BftProtocolSchedule schedule, - final List
validators, - final BlockHeader parentHeader, - final BlockHeader blockHeader, - final int block) { - return schedule - .getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp()) - .getBlockHeaderValidator() - .validateHeader( - blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT); + @Module + static class IbftProtocolScheduleModule { + @Provides + @Singleton + NodeKey nodeKey() { + return NodeKeyUtils.generate(); + } + + @Provides + Address provideProposerAddress(final NodeKey proposerNodeKey) { + return Util.publicKeyToAddress(proposerNodeKey.getPublicKey()); + } + + @Provides + List
provideValidators(final Address proposerAddress) { + return singletonList(proposerAddress); + } + + @Provides + public BftExtraData mockBftExtraData(final List
validators) { + BftExtraData bftExtraData = mock(BftExtraData.class); + when(bftExtraData.getValidators()).thenReturn(validators); + return bftExtraData; + } + + @Provides + public BftExtraDataCodec mockBftExtraDataCodec(final BftExtraData bftExtraData) { + BftExtraDataCodec bftExtraDataCodec = mock(BftExtraDataCodec.class); + when(bftExtraDataCodec.decode(any())).thenReturn(bftExtraData); + return bftExtraDataCodec; + } + + @Provides + ProtocolContext protocolContext( + final List
validators, final BftExtraDataCodec bftExtraDataCodec) { + return new ProtocolContext( + null, + null, + setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec), + new BadBlockManager()); + } + } + + @Singleton + @Component(modules = {NoMiningParamters.class, IbftProtocolScheduleModule.class}) + interface TestEthCoreComponent extends EthereumCoreComponent { + ProtocolContext protocolContext(); + + List
validators(); + + NodeKey nodeKey(); + + BftExtraDataCodec bftExtraDataCodec(); } - private ProtocolContext protocolContext(final Collection
validators) { - return new ProtocolContext( - null, - null, - setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec), - new BadBlockManager()); + @Module + static class NoMiningParamters { + @Provides + MiningParameters provideMiningParameters() { + return MiningParameters.MINING_DISABLED; + } } } diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java index b9f57debb6..9ca5b0b8e1 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java @@ -180,7 +180,7 @@ public class IbftBlockHeightManagerTest { final ProtocolScheduleBuilder protocolScheduleBuilder = new ProtocolScheduleBuilder( new StubGenesisConfigOptions(), - BigInteger.ONE, + Optional.empty(), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeProtocolSchedule.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeProtocolSchedule.java index abbc3b130a..f794152a78 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeProtocolSchedule.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeProtocolSchedule.java @@ -101,7 +101,7 @@ public class MergeProtocolSchedule { return new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), new ProtocolSpecAdapters(postMergeModifications), privacyParameters, isRevertReasonEnabled, diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java index 190c87e020..23321f23cc 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java @@ -182,7 +182,7 @@ public class QbftBlockHeightManagerTest { final ProtocolScheduleBuilder protocolScheduleBuilder = new ProtocolScheduleBuilder( new StubGenesisConfigOptions(), - BigInteger.ONE, + Optional.of(BigInteger.ONE), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/AbstractJsonRpcExecutor.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/AbstractJsonRpcExecutor.java index 95dc88f6a5..f73d162fa1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/AbstractJsonRpcExecutor.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/AbstractJsonRpcExecutor.java @@ -106,6 +106,7 @@ public abstract class AbstractJsonRpcExecutor { private static HttpResponseStatus statusCodeFromError(final RpcErrorType error) { return switch (error) { case INVALID_REQUEST, PARSE_ERROR -> HttpResponseStatus.BAD_REQUEST; + case TIMEOUT_ERROR -> HttpResponseStatus.REQUEST_TIMEOUT; default -> HttpResponseStatus.OK; }; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandler.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandler.java index 278a38c557..8386631695 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandler.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandler.java @@ -34,6 +34,9 @@ import org.slf4j.LoggerFactory; public class JsonRpcExecutorHandler { private static final Logger LOG = LoggerFactory.getLogger(JsonRpcExecutorHandler.class); + // Default timeout for RPC calls in seconds + private static final long DEFAULT_TIMEOUT_MILLISECONDS = 30_000L; + private JsonRpcExecutorHandler() {} public static Handler handler( @@ -49,6 +52,19 @@ public class JsonRpcExecutorHandler { final Tracer tracer, final JsonRpcConfiguration jsonRpcConfiguration) { return ctx -> { + final long timerId = + ctx.vertx() + .setTimer( + DEFAULT_TIMEOUT_MILLISECONDS, + id -> { + final String method = + ctx.get(ContextKey.REQUEST_BODY_AS_JSON_OBJECT.name()).toString(); + LOG.error("Timeout occurred in JSON-RPC executor for method {}", method); + handleErrorAndEndResponse(ctx, null, RpcErrorType.TIMEOUT_ERROR); + }); + + ctx.put("timerId", timerId); + try { createExecutor(jsonRpcExecutor, tracer, ctx, jsonRpcConfiguration) .ifPresentOrElse( @@ -58,18 +74,38 @@ public class JsonRpcExecutorHandler { } catch (IOException e) { final String method = executor.getRpcMethodName(ctx); LOG.error("{} - Error streaming JSON-RPC response", method, e); - handleJsonRpcError(ctx, null, RpcErrorType.INTERNAL_ERROR); + handleErrorAndEndResponse(ctx, null, RpcErrorType.INTERNAL_ERROR); + } finally { + cancelTimer(ctx); } }, - () -> handleJsonRpcError(ctx, null, RpcErrorType.PARSE_ERROR)); + () -> { + handleErrorAndEndResponse(ctx, null, RpcErrorType.PARSE_ERROR); + cancelTimer(ctx); + }); } catch (final RuntimeException e) { - final String method = ctx.get(ContextKey.REQUEST_BODY_AS_JSON_OBJECT.name()); + final String method = ctx.get(ContextKey.REQUEST_BODY_AS_JSON_OBJECT.name()).toString(); LOG.error("Unhandled exception in JSON-RPC executor for method {}", method, e); - handleJsonRpcError(ctx, null, RpcErrorType.INTERNAL_ERROR); + handleErrorAndEndResponse(ctx, null, RpcErrorType.INTERNAL_ERROR); + cancelTimer(ctx); } }; } + private static void cancelTimer(final RoutingContext ctx) { + Long timerId = ctx.get("timerId"); + if (timerId != null) { + ctx.vertx().cancelTimer(timerId); + } + } + + private static void handleErrorAndEndResponse( + final RoutingContext ctx, final Object id, final RpcErrorType errorType) { + if (!ctx.response().ended()) { + handleJsonRpcError(ctx, id, errorType); + } + } + private static Optional createExecutor( final JsonRpcExecutor jsonRpcExecutor, final Tracer tracer, diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java index 00b0f83054..8d6bd7e433 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2.java @@ -61,11 +61,11 @@ public class EngineNewPayloadV2 extends AbstractEngineNewPayload { final Optional> maybeRequestsParam) { if (payloadParameter.getBlobGasUsed() != null) { return ValidationResult.invalid( - RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field"); + RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Unexpected blob gas used field present"); } if (payloadParameter.getExcessBlobGas() != null) { return ValidationResult.invalid( - RpcErrorType.INVALID_EXCESS_BLOB_GAS_PARAMS, "Missing excess blob gas field"); + RpcErrorType.INVALID_EXCESS_BLOB_GAS_PARAMS, "Unexpected excess blob gas field present"); } return ValidationResult.valid(); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandlerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandlerTest.java new file mode 100644 index 0000000000..ee00e433b2 --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/handlers/JsonRpcExecutorHandlerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.handlers; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; +import org.hyperledger.besu.ethereum.api.jsonrpc.context.ContextKey; +import org.hyperledger.besu.ethereum.api.jsonrpc.execution.JsonRpcExecutor; + +import io.netty.handler.codec.http.HttpResponseStatus; +import io.opentelemetry.api.trace.Tracer; +import io.vertx.core.Handler; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.RoutingContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +class JsonRpcExecutorHandlerTest { + + private JsonRpcExecutor mockExecutor; + private Tracer mockTracer; + private JsonRpcConfiguration mockConfig; + private RoutingContext mockContext; + private Vertx mockVertx; + private HttpServerResponse mockResponse; + + @BeforeEach + void setUp() { + mockExecutor = mock(JsonRpcExecutor.class); + mockTracer = mock(Tracer.class); + mockConfig = mock(JsonRpcConfiguration.class); + mockContext = mock(RoutingContext.class); + mockVertx = mock(Vertx.class); + mockResponse = mock(HttpServerResponse.class); + + when(mockContext.vertx()).thenReturn(mockVertx); + when(mockContext.response()).thenReturn(mockResponse); + when(mockResponse.ended()).thenReturn(false); + when(mockResponse.setStatusCode(anyInt())).thenReturn(mockResponse); + } + + @Test + void testTimeoutHandling() { + // Arrange + Handler handler = + JsonRpcExecutorHandler.handler(mockExecutor, mockTracer, mockConfig); + ArgumentCaptor delayCaptor = ArgumentCaptor.forClass(Long.class); + @SuppressWarnings("unchecked") + ArgumentCaptor> timerHandlerCaptor = ArgumentCaptor.forClass(Handler.class); + + when(mockContext.get(eq(ContextKey.REQUEST_BODY_AS_JSON_OBJECT.name()))).thenReturn("{}"); + when(mockVertx.setTimer(delayCaptor.capture(), timerHandlerCaptor.capture())).thenReturn(1L); + when(mockContext.get("timerId")).thenReturn(1L); + + // Act + handler.handle(mockContext); + + // Assert + verify(mockVertx).setTimer(eq(30000L), any()); + + // Simulate timeout + timerHandlerCaptor.getValue().handle(1L); + + // Verify timeout handling + verify(mockResponse, times(1)) + .setStatusCode(eq(HttpResponseStatus.REQUEST_TIMEOUT.code())); // Expect 408 Request Timeout + verify(mockResponse, times(1)).end(contains("Timeout expired")); + verify(mockVertx, times(1)).cancelTimer(1L); + } + + @Test + void testCancelTimerOnSuccessfulExecution() { + // Arrange + Handler handler = + JsonRpcExecutorHandler.handler(mockExecutor, mockTracer, mockConfig); + when(mockContext.get(eq(ContextKey.REQUEST_BODY_AS_JSON_OBJECT.name()))).thenReturn("{}"); + when(mockVertx.setTimer(anyLong(), any())).thenReturn(1L); + when(mockContext.get("timerId")).thenReturn(1L); + + // Act + handler.handle(mockContext); + + // Assert + verify(mockVertx).setTimer(anyLong(), any()); + verify(mockVertx).cancelTimer(1L); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index e793ee8b57..0b81ac111a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.ACCEPTED; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID; @@ -51,7 +52,6 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; @@ -62,7 +62,6 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.rpc.RpcResponseType; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -123,12 +122,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.empty(), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); assertValidResponse(mockHeader, resp); } @@ -136,12 +134,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnInvalidOnBlockExecutionError() { BlockHeader mockHeader = - setupValidPayload( - new BlockProcessingResult("error 42"), Optional.empty(), Optional.empty()); + setupValidPayload(new BlockProcessingResult("error 42"), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash().get()).isEqualTo(mockHash); @@ -152,14 +149,14 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnAcceptedOnLatestValidAncestorEmpty() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); when(mergeCoordinator.getLatestValidAncestor(any(BlockHeader.class))) .thenReturn(Optional.empty()); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash()).isEmpty(); @@ -170,20 +167,19 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnSuccessOnAlreadyPresent() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); - Block mockBlock = - new Block(mockHeader, new BlockBody(Collections.emptyList(), Collections.emptyList())); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); + Block mockBlock = new Block(mockHeader, new BlockBody(emptyList(), emptyList())); when(blockchain.getBlockByHash(any())).thenReturn(Optional.of(mockBlock)); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); assertValidResponse(mockHeader, resp); } @Test public void shouldReturnInvalidWithLatestValidHashIsABadBlock() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); Hash latestValidHash = Hash.hash(Bytes32.fromHexStringLenient("0xcafebabe")); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); @@ -191,7 +187,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT when(mergeCoordinator.getLatestValidHashOfBadBlock(mockHeader.getHash())) .thenReturn(Optional.of(latestValidHash)); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash()).isEqualTo(Optional.of(latestValidHash)); @@ -204,12 +200,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.empty(), new StorageException("database bedlam")), - Optional.empty(), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); fromErrorResp(resp); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -220,13 +215,12 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.empty(), new MerkleTrieException("missing leaf")), - Optional.empty(), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -235,7 +229,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldNotReturnInvalidOnThrownMerkleTrieException() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -243,7 +237,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT .thenReturn(Optional.of(mockHash)); when(mergeCoordinator.rememberBlock(any())).thenThrow(new MerkleTrieException("missing leaf")); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -252,7 +246,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnInvalidBlockHashOnBadHashParameter() { - BlockHeader mockHeader = spy(createBlockHeader(Optional.empty(), Optional.empty())); + BlockHeader mockHeader = spy(createBlockHeader(Optional.empty())); lenient() .when(mergeCoordinator.getLatestValidAncestor(mockHeader.getBlockHash())) .thenReturn(Optional.empty()); @@ -260,7 +254,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); lenient().when(mockHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337")); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getStatusAsString()).isEqualTo(getExpectedInvalidBlockHashStatus().name()); @@ -269,11 +263,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldCheckBlockValidityBeforeCheckingByHashForExisting() { - BlockHeader realHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader realHeader = createBlockHeader(Optional.empty()); BlockHeader paramHeader = spy(realHeader); when(paramHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337")); - var resp = resp(mockEnginePayload(paramHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(paramHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash()).isEmpty(); @@ -283,7 +277,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnInvalidOnMalformedTransactions() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); when(mergeCoordinator.getLatestValidAncestor(any(Hash.class))) .thenReturn(Optional.of(mockHash)); @@ -298,9 +292,9 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldRespondWithSyncingDuringForwardSync() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); when(mergeContext.isSyncing()).thenReturn(Boolean.TRUE); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getError()).isNull(); @@ -311,10 +305,10 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldRespondWithSyncingDuringBackwardsSync() { - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); when(mergeCoordinator.appendNewPayloadToSync(any())) .thenReturn(CompletableFuture.completedFuture(null)); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash()).isEmpty(); @@ -325,12 +319,12 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldRespondWithInvalidIfExtraDataIsNull() { - BlockHeader realHeader = createBlockHeader(Optional.empty(), Optional.empty()); + BlockHeader realHeader = createBlockHeader(Optional.empty()); BlockHeader paramHeader = spy(realHeader); when(paramHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337")); when(paramHeader.getExtraData().toHexString()).thenReturn(null); - var resp = resp(mockEnginePayload(paramHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(paramHeader, emptyList())); EnginePayloadStatusResult res = fromSuccessResp(resp); assertThat(res.getLatestValidHash()).isEmpty(); @@ -342,8 +336,8 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT @Test public void shouldReturnInvalidWhenBadBlock() { when(mergeCoordinator.isBadBlock(any(Hash.class))).thenReturn(true); - BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + BlockHeader mockHeader = createBlockHeader(Optional.empty()); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); when(protocolSpec.getWithdrawalsValidator()) .thenReturn(new WithdrawalsValidator.AllowedWithdrawals()); EnginePayloadStatusResult res = fromSuccessResp(resp); @@ -359,12 +353,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.empty(), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); assertValidResponse(mockHeader, resp); } @@ -408,11 +401,9 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT } protected BlockHeader setupValidPayload( - final BlockProcessingResult value, - final Optional> maybeWithdrawals, - final Optional> maybeRequests) { + final BlockProcessingResult value, final Optional> maybeWithdrawals) { - BlockHeader mockHeader = createBlockHeader(maybeWithdrawals, maybeRequests); + BlockHeader mockHeader = createBlockHeader(maybeWithdrawals); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(mergeCoordinator.getLatestValidAncestor(any(BlockHeader.class))) .thenReturn(Optional.of(mockHash)); @@ -425,6 +416,11 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT } protected EnginePayloadStatusResult fromSuccessResp(final JsonRpcResponse resp) { + if (resp.getType().equals(RpcResponseType.ERROR)) { + final JsonRpcError jsonRpcError = fromErrorResp(resp); + throw new AssertionError( + "Expected success but was error with message: " + jsonRpcError.getMessage()); + } assertThat(resp.getType()).isEqualTo(RpcResponseType.SUCCESS); return Optional.of(resp) .map(JsonRpcSuccessResponse.class::cast) @@ -441,15 +437,12 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT .get(); } - protected BlockHeader createBlockHeader( - final Optional> maybeWithdrawals, - final Optional> maybeRequests) { - return createBlockHeaderFixture(maybeWithdrawals, maybeRequests).buildHeader(); + protected BlockHeader createBlockHeader(final Optional> maybeWithdrawals) { + return createBlockHeaderFixture(maybeWithdrawals).buildHeader(); } protected BlockHeaderTestFixture createBlockHeaderFixture( - final Optional> maybeWithdrawals, - final Optional> maybeRequests) { + final Optional> maybeWithdrawals) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture().baseFeePerGas(Wei.ONE).buildHeader(); return new BlockHeaderTestFixture() @@ -458,8 +451,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT .number(parentBlockHeader.getNumber() + 1) .timestamp(parentBlockHeader.getTimestamp() + 1) .withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null)) - .parentBeaconBlockRoot(maybeParentBeaconBlockRoot) - .requestsHash(maybeRequests.map(BodyValidation::requestsHash).orElse(null)); + .parentBeaconBlockRoot(maybeParentBeaconBlockRoot); } protected void assertValidResponse(final BlockHeader mockHeader, final JsonRpcResponse resp) { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java index abf2c29767..171ee0499f 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java @@ -82,8 +82,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.of(withdrawals), - Optional.empty()); + Optional.of(withdrawals)); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -100,7 +99,6 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.empty(), Optional.empty()); lenient() .when(blockchain.getBlockHeader(mockHeader.getParentHash())) @@ -120,7 +118,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { var resp = resp( mockEnginePayload( - createBlockHeader(Optional.of(Collections.emptyList()), Optional.empty()), + createBlockHeader(Optional.of(Collections.emptyList())), Collections.emptyList(), withdrawals)); @@ -133,14 +131,14 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { public void shouldValidateBlobGasUsedCorrectly() { // V2 should return error if non-null blobGasUsed BlockHeader blockHeader = - createBlockHeaderFixture(Optional.of(Collections.emptyList()), Optional.empty()) + createBlockHeaderFixture(Optional.of(Collections.emptyList())) .blobGasUsed(100L) .buildHeader(); var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of())); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_BLOB_GAS_USED_PARAMS.getCode()); - assertThat(jsonRpcError.getData()).isEqualTo("Missing blob gas used field"); + assertThat(jsonRpcError.getData()).isEqualTo("Unexpected blob gas used field present"); verify(engineCallListener, times(1)).executionEngineCalled(); } @@ -148,7 +146,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { public void shouldValidateExcessBlobGasCorrectly() { // V2 should return error if non-null ExcessBlobGas BlockHeader blockHeader = - createBlockHeaderFixture(Optional.of(Collections.emptyList()), Optional.empty()) + createBlockHeaderFixture(Optional.of(Collections.emptyList())) .excessBlobGas(BlobGas.MAX_BLOB_GAS) .buildHeader(); @@ -156,7 +154,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); - assertThat(jsonRpcError.getData()).isEqualTo("Missing excess blob gas field"); + assertThat(jsonRpcError.getData()).isEqualTo("Unexpected excess blob gas field present"); verify(engineCallListener, times(1)).executionEngineCalled(); } @@ -169,9 +167,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { var resp = resp( mockEnginePayload( - createBlockHeader(Optional.empty(), Optional.empty()), - Collections.emptyList(), - withdrawals)); + createBlockHeader(Optional.empty()), Collections.emptyList(), withdrawals)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -182,7 +178,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest { // Cancun starte at timestamp 30 final long blockTimestamp = 31L; BlockHeader blockHeader = - createBlockHeaderFixture(Optional.of(Collections.emptyList()), Optional.empty()) + createBlockHeaderFixture(Optional.of(Collections.emptyList())) .timestamp(blockTimestamp) .buildHeader(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java index b79cb587eb..1810ce9450 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_PARAMS; @@ -44,7 +45,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EnginePayloadS import org.hyperledger.besu.ethereum.core.BlobTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; import org.hyperledger.besu.ethereum.core.Withdrawal; @@ -56,7 +56,6 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import java.math.BigInteger; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Supplier; @@ -112,8 +111,18 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { when(payload.getExcessBlobGas()).thenReturn("99"); when(payload.getBlobGasUsed()).thenReturn(9l); + // TODO locking this as V3 otherwise this breaks the EngineNewPayloadV4Test subclass when method + // field is V4 + final EngineNewPayloadV3 methodV3 = + new EngineNewPayloadV3( + vertx, + protocolSchedule, + protocolContext, + mergeCoordinator, + ethPeers, + engineCallListener); final JsonRpcResponse badParam = - method.response( + methodV3.response( new JsonRpcRequestContext( new JsonRpcRequest( "2.0", @@ -133,24 +142,20 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { final BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.empty(), Optional.empty()); - final EnginePayloadParameter payload = - mockEnginePayload(mockHeader, Collections.emptyList(), null); + final EnginePayloadParameter payload = mockEnginePayload(mockHeader, emptyList(), null); ValidationResult res = method.validateParameters( payload, Optional.of(List.of()), Optional.of("0x0000000000000000000000000000000000000000000000000000000000000000"), - Optional.empty()); + Optional.of(emptyList())); assertThat(res.isValid()).isTrue(); } @Override - protected BlockHeader createBlockHeader( - final Optional> maybeWithdrawals, - final Optional> maybeRequests) { + protected BlockHeader createBlockHeader(final Optional> maybeWithdrawals) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture() .baseFeePerGas(Wei.ONE) @@ -186,12 +191,12 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { public void shouldValidateBlobGasUsedCorrectly() { // V3 must return error if null blobGasUsed BlockHeader blockHeader = - createBlockHeaderFixture(Optional.of(Collections.emptyList()), Optional.empty()) + createBlockHeaderFixture(Optional.of(emptyList())) .excessBlobGas(BlobGas.MAX_BLOB_GAS) .blobGasUsed(null) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of())); + var resp = resp(mockEnginePayload(blockHeader, emptyList(), List.of())); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -204,12 +209,12 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { public void shouldValidateExcessBlobGasCorrectly() { // V3 must return error if null excessBlobGas BlockHeader blockHeader = - createBlockHeaderFixture(Optional.of(Collections.emptyList()), Optional.empty()) + createBlockHeaderFixture(Optional.of(emptyList())) .excessBlobGas(null) .blobGasUsed(100L) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of())); + var resp = resp(mockEnginePayload(blockHeader, emptyList(), List.of())); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -229,7 +234,6 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.empty(), Optional.empty()); var resp = resp(mockEnginePayload(mockHeader, transactions)); @@ -265,7 +269,7 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test { protected JsonRpcResponse resp(final EnginePayloadParameter payload) { Object[] params = maybeParentBeaconBlockRoot - .map(bytes32 -> new Object[] {payload, Collections.emptyList(), bytes32.toHexString()}) + .map(bytes32 -> new Object[] {payload, emptyList(), bytes32.toHexString()}) .orElseGet(() -> new Object[] {payload}); return method.response( new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java index c8504e7451..fe7c38917c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java @@ -14,8 +14,10 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.api.graphql.internal.response.GraphQLError.INVALID_PARAMS; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_EXECUTION_REQUESTS_PARAMS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; @@ -42,7 +44,6 @@ import org.hyperledger.besu.ethereum.mainnet.requests.MainnetRequestsValidator; import org.hyperledger.besu.ethereum.mainnet.requests.ProhibitedRequestValidator; import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; @@ -59,14 +60,19 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test { public EngineNewPayloadV4Test() {} + private static final List VALID_REQUESTS = + List.of( + new Request(RequestType.DEPOSIT, Bytes.of(1)), + new Request(RequestType.WITHDRAWAL, Bytes.of(1)), + new Request(RequestType.CONSOLIDATION, Bytes.of(1))); + @BeforeEach @Override public void before() { super.before(); maybeParentBeaconBlockRoot = Optional.of(Bytes32.ZERO); - // TODO this should be using NewPayloadV4 this.method = - new EngineNewPayloadV3( + new EngineNewPayloadV4( vertx, protocolSchedule, protocolContext, @@ -75,95 +81,63 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test { engineCallListener); lenient().when(protocolSchedule.hardforkFor(any())).thenReturn(Optional.of(pragueHardfork)); lenient().when(protocolSpec.getGasCalculator()).thenReturn(new PragueGasCalculator()); + mockAllowedRequestsValidator(); } @Override public void shouldReturnExpectedMethodName() { - assertThat(method.getName()).isEqualTo("engine_newPayloadV3"); - } - - @Test - public void shouldReturnValidIfRequestsIsNull_WhenRequestsProhibited() { - mockProhibitedRequestsValidator(); - - BlockHeader mockHeader = - setupValidPayload( - new BlockProcessingResult( - Optional.of(new BlockProcessingOutputs(null, List.of(), Optional.empty()))), - Optional.empty(), - Optional.empty()); - when(blockchain.getBlockHeader(mockHeader.getParentHash())) - .thenReturn(Optional.of(mock(BlockHeader.class))); - when(mergeCoordinator.getLatestValidAncestor(mockHeader)) - .thenReturn(Optional.of(mockHeader.getHash())); - - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList())); - - assertValidResponse(mockHeader, resp); + assertThat(method.getName()).isEqualTo("engine_newPayloadV4"); } @Test public void shouldReturnInvalidIfRequestsIsNull_WhenRequestsAllowed() { - mockAllowedRequestsValidator(); var resp = - resp( - mockEnginePayload( - createBlockHeader(Optional.empty(), Optional.empty()), Collections.emptyList())); + respWithInvalidRequests( + mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList())); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); + assertThat(fromErrorResp(resp).getMessage()) + .isEqualTo(INVALID_EXECUTION_REQUESTS_PARAMS.getMessage()); verify(engineCallListener, times(1)).executionEngineCalled(); } @Test public void shouldReturnValidIfRequestsIsNotNull_WhenRequestsAllowed() { - final List requests = - List.of( - new Request(RequestType.DEPOSIT, Bytes.of(1)), - new Request(RequestType.WITHDRAWAL, Bytes.of(1)), - new Request(RequestType.CONSOLIDATION, Bytes.of(1))); - - mockAllowedRequestsValidator(); BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult( - Optional.of(new BlockProcessingOutputs(null, List.of(), Optional.of(requests)))), - Optional.empty(), + Optional.of( + new BlockProcessingOutputs(null, List.of(), Optional.of(VALID_REQUESTS)))), Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); when(mergeCoordinator.getLatestValidAncestor(mockHeader)) .thenReturn(Optional.of(mockHeader.getHash())); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()), requests); + var resp = resp(mockEnginePayload(mockHeader, emptyList())); assertValidResponse(mockHeader, resp); } @Test public void shouldReturnInvalidIfRequestsIsNotNull_WhenRequestsProhibited() { - final List requests = - List.of( - new Request(RequestType.DEPOSIT, Bytes.of(1)), - new Request(RequestType.WITHDRAWAL, Bytes.of(1)), - new Request(RequestType.CONSOLIDATION, Bytes.of(1))); - mockProhibitedRequestsValidator(); - var resp = - resp( - mockEnginePayload( - createBlockHeader(Optional.empty(), Optional.of(Collections.emptyList())), - Collections.emptyList()), - requests); + var resp = resp(mockEnginePayload(createValidBlockHeaderForV4(Optional.empty()), emptyList())); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); } - @Override - protected BlockHeader createBlockHeader( - final Optional> maybeWithdrawals, - final Optional> maybeRequests) { + private BlockHeader createValidBlockHeaderForV4( + final Optional> maybeWithdrawals) { + return createBlockHeaderFixtureForV3(maybeWithdrawals) + .requestsHash(BodyValidation.requestsHash(VALID_REQUESTS)) + .buildHeader(); + } + + private BlockHeaderTestFixture createBlockHeaderFixtureForV3( + final Optional> maybeWithdrawals) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture() .baseFeePerGas(Wei.ONE) @@ -172,48 +146,49 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test { .blobGasUsed(0L) .buildHeader(); - BlockHeader mockHeader = - new BlockHeaderTestFixture() - .baseFeePerGas(Wei.ONE) - .parentHash(parentBlockHeader.getParentHash()) - .number(parentBlockHeader.getNumber() + 1) - .timestamp(parentBlockHeader.getTimestamp() + 1) - .withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null)) - .excessBlobGas(BlobGas.ZERO) - .blobGasUsed(0L) - .requestsHash(maybeRequests.map(BodyValidation::requestsHash).orElse(null)) - .parentBeaconBlockRoot( - maybeParentBeaconBlockRoot.isPresent() ? maybeParentBeaconBlockRoot : null) - .buildHeader(); - return mockHeader; + return new BlockHeaderTestFixture() + .baseFeePerGas(Wei.ONE) + .parentHash(parentBlockHeader.getParentHash()) + .number(parentBlockHeader.getNumber() + 1) + .timestamp(parentBlockHeader.getTimestamp() + 1) + .withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null)) + .excessBlobGas(BlobGas.ZERO) + .blobGasUsed(0L) + .parentBeaconBlockRoot( + maybeParentBeaconBlockRoot.isPresent() ? maybeParentBeaconBlockRoot : null); + } + + @Override + protected BlockHeader createBlockHeader(final Optional> maybeWithdrawals) { + return createValidBlockHeaderForV4(maybeWithdrawals); } @Override protected JsonRpcResponse resp(final EnginePayloadParameter payload) { + final List requestsWithoutRequestId = + VALID_REQUESTS.stream() + .sorted(Comparator.comparing(Request::getType)) + .map(r -> r.getData().toHexString()) + .toList(); Object[] params = maybeParentBeaconBlockRoot - .map(bytes32 -> new Object[] {payload, Collections.emptyList(), bytes32.toHexString()}) + .map( + bytes32 -> + new Object[] { + payload, emptyList(), bytes32.toHexString(), requestsWithoutRequestId + }) .orElseGet(() -> new Object[] {payload}); return method.response( new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params))); } - protected JsonRpcResponse resp( - final EnginePayloadParameter payload, final List requests) { - final List requestsWithoutRequestId = - requests.stream() - .sorted(Comparator.comparing(Request::getType)) - .map(r -> r.getData().toHexString()) - .toList(); + protected JsonRpcResponse respWithInvalidRequests(final EnginePayloadParameter payload) { Object[] params = maybeParentBeaconBlockRoot .map( bytes32 -> - new Object[] { - payload, - Collections.emptyList(), - bytes32.toHexString(), - requestsWithoutRequestId + new Object[] {payload, emptyList(), bytes32.toHexString() + // empty requests param is invalid }) .orElseGet(() -> new Object[] {payload}); return method.response( diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index d30349e3d0..727cfd440f 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -304,7 +304,7 @@ abstract class AbstractBlockCreatorTest { .protocolSchedule( new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), protocolSpecAdapters, PrivacyParameters.DEFAULT, false, diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java index 940d076bbc..731b8b3854 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java @@ -42,6 +42,7 @@ import org.hyperledger.besu.testutil.TestClock; import org.hyperledger.besu.util.number.Fraction; import java.time.ZoneId; +import java.util.Optional; import java.util.function.Function; public class LegacyFeeMarketBlockTransactionSelectorTest @@ -56,7 +57,7 @@ public class LegacyFeeMarketBlockTransactionSelectorTest protected ProtocolSchedule createProtocolSchedule() { return new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - CHAIN_ID, + Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java index 68d9a71de6..3bb559550b 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java @@ -51,6 +51,7 @@ import org.hyperledger.besu.util.number.Fraction; import java.time.ZoneId; import java.util.List; +import java.util.Optional; import java.util.function.Function; import org.junit.jupiter.api.Test; @@ -67,7 +68,7 @@ public class LondonFeeMarketBlockTransactionSelectorTest protected ProtocolSchedule createProtocolSchedule() { return new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - CHAIN_ID, + Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index 509efd7b19..8e7f992ad5 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -62,6 +62,7 @@ import org.hyperledger.besu.util.Subscribers; import java.io.IOException; import java.math.BigInteger; import java.util.Collections; +import java.util.Optional; import java.util.function.Function; import com.google.common.collect.Lists; @@ -93,7 +94,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { .protocolSchedule( new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, false, @@ -152,7 +153,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { .protocolSchedule( new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> @@ -208,7 +209,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> @@ -285,7 +286,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> diff --git a/ethereum/core/build.gradle b/ethereum/core/build.gradle index 912d8673a5..c5ab446266 100644 --- a/ethereum/core/build.gradle +++ b/ethereum/core/build.gradle @@ -107,6 +107,8 @@ dependencies { testSupportImplementation 'org.junit.jupiter:junit-jupiter' testSupportImplementation 'org.assertj:assertj-core' testSupportImplementation 'org.mockito:mockito-core' + testSupportImplementation 'com.google.dagger:dagger' + testSupportAnnotationProcessor 'com.google.dagger:dagger-compiler' jmhImplementation project(path: ':config', configuration: 'testSupportArtifacts') jmhImplementation project(':crypto:algorithms') diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolScheduleModule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolScheduleModule.java new file mode 100644 index 0000000000..039747db0b --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolScheduleModule.java @@ -0,0 +1,100 @@ +/* + * 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.components; + +import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.ethereum.chain.BadBlockManager; +import org.hyperledger.besu.ethereum.core.MiningParameters; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; +import org.hyperledger.besu.ethereum.mainnet.DefaultProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; +import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.plugin.services.MetricsSystem; + +import java.math.BigInteger; +import java.util.Optional; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +/** Provides the protocol schedule for the network. */ +@Module +public class ProtocolScheduleModule { + + /** Default constructor. */ + public ProtocolScheduleModule() {} + + /** + * Provides the protocol schedule builder. + * + * @param config the genesis config options + * @param protocolSpecAdapters the protocol spec adapters + * @param privacyParameters the privacy parameters + * @param isRevertReasonEnabled whether revert reason is enabled + * @param evmConfiguration the EVM configuration + * @param badBlockManager the bad block manager + * @param isParallelTxProcessingEnabled whether parallel tx processing is enabled + * @param metricsSystem the metrics system + * @param miningParameters the mining parameters + * @return the protocol schedule builder + */ + @Singleton + @Provides + public ProtocolScheduleBuilder provideProtocolScheduleBuilder( + final GenesisConfigOptions config, + final ProtocolSpecAdapters protocolSpecAdapters, + final PrivacyParameters privacyParameters, + final boolean isRevertReasonEnabled, + final EvmConfiguration evmConfiguration, + final BadBlockManager badBlockManager, + final boolean isParallelTxProcessingEnabled, + final MetricsSystem metricsSystem, + final MiningParameters miningParameters) { + + ProtocolScheduleBuilder builder = + new ProtocolScheduleBuilder( + config, + config.getChainId(), + protocolSpecAdapters, + privacyParameters, + isRevertReasonEnabled, + evmConfiguration, + miningParameters, + badBlockManager, + isParallelTxProcessingEnabled, + metricsSystem); + + return builder; + } + + /** + * Provides the protocol schedule. + * + * @param builder the protocol schedule builder + * @param config the genesis config options + * @return the protocol schedule + */ + @Provides + public ProtocolSchedule createProtocolSchedule( + final ProtocolScheduleBuilder builder, final GenesisConfigOptions config) { + final Optional chainId = config.getChainId().or(() -> builder.getDefaultChainId()); + DefaultProtocolSchedule protocolSchedule = new DefaultProtocolSchedule(chainId); + builder.initSchedule(protocolSchedule, chainId); + return protocolSchedule; + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolSpecModule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolSpecModule.java new file mode 100644 index 0000000000..fe9b0f3fab --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/components/ProtocolSpecModule.java @@ -0,0 +1,51 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.components; + +import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSpecs; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder; +import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.plugin.services.MetricsSystem; + +import javax.inject.Named; + +import dagger.Module; +import dagger.Provides; + +/** Provides protocol specs for network forks. */ +@Module +public class ProtocolSpecModule { + + /** Default constructor. */ + public ProtocolSpecModule() {} + + /** + * Provides the protocol spec for the frontier network fork. + * + * @param evmConfiguration the EVM configuration + * @param isParalleltxEnabled whether parallel tx processing is enabled + * @param metricsSystem the metrics system + * @return the protocol spec for the frontier network fork + */ + @Provides + @Named("frontier") + public ProtocolSpecBuilder frontierProtocolSpec( + final EvmConfiguration evmConfiguration, + final boolean isParalleltxEnabled, + final MetricsSystem metricsSystem) { + return MainnetProtocolSpecs.frontierDefinition( + evmConfiguration, isParalleltxEnabled, metricsSystem); + } +} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethConfiguration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/CoinbaseModule.java similarity index 60% rename from ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethConfiguration.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/CoinbaseModule.java index bb4fa31a55..bb613b4e17 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethConfiguration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/CoinbaseModule.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright contributors to Hyperledger Besu. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -12,19 +12,20 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.retesteth; +package org.hyperledger.besu.ethereum.core.components; -import java.nio.file.Path; +import org.hyperledger.besu.datatypes.Address; -public class RetestethConfiguration { +import javax.inject.Named; - private final Path dataPath; +import dagger.Module; +import dagger.Provides; - public RetestethConfiguration(final Path dataPath) { - this.dataPath = dataPath; - } - - Path getDataPath() { - return dataPath; +@Module +public class CoinbaseModule { + @Provides + @Named("emptyCoinbase") + Address provideEmptyCoinbase() { + return Address.fromHexString(String.format("%020x", 1)); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/EthereumCoreComponent.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/EthereumCoreComponent.java new file mode 100644 index 0000000000..2b081399a9 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/EthereumCoreComponent.java @@ -0,0 +1,32 @@ +/* + * 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.core.components; + +import org.hyperledger.besu.ethereum.components.ProtocolScheduleModule; +import org.hyperledger.besu.ethereum.core.MiningParameters; + +import javax.inject.Singleton; + +import dagger.Subcomponent; + +@Singleton +@Subcomponent( + modules = { + MiningParametersModule.class, + ProtocolScheduleModule.class, + }) +public interface EthereumCoreComponent { + MiningParameters getMiningParameters(); +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/MiningParametersModule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/MiningParametersModule.java new file mode 100644 index 0000000000..8551d0e946 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/components/MiningParametersModule.java @@ -0,0 +1,64 @@ +/* + * 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.core.components; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.MiningParameters; + +import javax.inject.Named; + +import dagger.Module; +import dagger.Provides; + +@Module +public class MiningParametersModule { + + @Provides + @Named("defaultMiningParameters") + protected MiningParameters createImmutableMiningParams() { + return ImmutableMiningParameters.builder().build(); + } + + @Provides + @Named("noMining") + protected MiningParameters createNoMining() { + return ImmutableMiningParameters.builder() + .mutableInitValues( + ImmutableMiningParameters.MutableInitValues.builder().isMiningEnabled(false).build()) + .build(); + } + + @Provides + @Named("zeroGas") + MiningParameters createZeroGasMining(final @Named("emptyCoinbase") Address coinbase) { + final MiningParameters miningParameters = + ImmutableMiningParameters.builder() + .mutableInitValues( + ImmutableMiningParameters.MutableInitValues.builder() + .isMiningEnabled(true) + .minTransactionGasPrice(Wei.ZERO) + .coinbase(coinbase) + .build()) + .build(); + return miningParameters; + } + + @Provides + MiningParameters provideMiningParameters() { + throw new IllegalStateException("unimplemented"); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java index b86b2b0de2..4290679bae 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java @@ -24,7 +24,12 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.plugin.services.MetricsSystem; -/** A ProtocolSchedule which behaves similarly to MainNet, but with a much reduced difficulty. */ +import java.util.Optional; + +/** + * A ProtocolSchedule which behaves similarly to pre-merge MainNet, but with a much reduced + * difficulty. + */ public class FixedDifficultyProtocolSchedule { public static ProtocolSchedule create( @@ -38,6 +43,7 @@ public class FixedDifficultyProtocolSchedule { final MetricsSystem metricsSystem) { return new ProtocolScheduleBuilder( config, + Optional.empty(), ProtocolSpecAdapters.create( 0, builder -> diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java index 88b6a5ae1b..e6c372a682 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.plugin.services.MetricsSystem; import java.math.BigInteger; +import java.util.Optional; import java.util.function.Function; /** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */ @@ -47,9 +48,9 @@ public class MainnetProtocolSchedule { */ public static ProtocolSchedule fromConfig( final GenesisConfigOptions config, - final PrivacyParameters privacyParameters, - final boolean isRevertReasonEnabled, - final EvmConfiguration evmConfiguration, + final Optional privacyParameters, + final Optional isRevertReasonEnabled, + final Optional evmConfiguration, final MiningParameters miningParameters, final BadBlockManager badBlockManager, final boolean isParallelTxProcessingEnabled, @@ -57,9 +58,9 @@ public class MainnetProtocolSchedule { if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) { return FixedDifficultyProtocolSchedule.create( config, - privacyParameters, - isRevertReasonEnabled, - evmConfiguration, + privacyParameters.orElse(PrivacyParameters.DEFAULT), + isRevertReasonEnabled.orElse(false), + evmConfiguration.orElse(EvmConfiguration.DEFAULT), miningParameters, badBlockManager, isParallelTxProcessingEnabled, @@ -67,11 +68,11 @@ public class MainnetProtocolSchedule { } return new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), - privacyParameters, - isRevertReasonEnabled, - evmConfiguration, + privacyParameters.orElse(PrivacyParameters.DEFAULT), + isRevertReasonEnabled.orElse(false), + evmConfiguration.orElse(EvmConfiguration.DEFAULT), miningParameters, badBlockManager, isParallelTxProcessingEnabled, @@ -101,9 +102,9 @@ public class MainnetProtocolSchedule { final MetricsSystem metricsSystem) { return fromConfig( config, - PrivacyParameters.DEFAULT, - isRevertReasonEnabled, - evmConfiguration, + Optional.empty(), + Optional.of(isRevertReasonEnabled), + Optional.of(evmConfiguration), miningParameters, badBlockManager, isParallelTxProcessingEnabled, @@ -130,9 +131,9 @@ public class MainnetProtocolSchedule { final MetricsSystem metricsSystem) { return fromConfig( config, - PrivacyParameters.DEFAULT, - false, - evmConfiguration, + Optional.empty(), + Optional.empty(), + Optional.of(evmConfiguration), miningParameters, badBlockManager, isParallelTxProcessingEnabled, @@ -157,9 +158,9 @@ public class MainnetProtocolSchedule { final MetricsSystem metricsSystem) { return fromConfig( config, - PrivacyParameters.DEFAULT, - false, - EvmConfiguration.DEFAULT, + Optional.empty(), + Optional.empty(), + Optional.empty(), miningParameters, badBlockManager, isParallelTxProcessingEnabled, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index 52003bc96c..fd27ca0574 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -48,59 +48,12 @@ public class ProtocolScheduleBuilder { private final PrivacyParameters privacyParameters; private final boolean isRevertReasonEnabled; private final EvmConfiguration evmConfiguration; - private final MiningParameters miningParameters; private final BadBlockManager badBlockManager; private final boolean isParallelTxProcessingEnabled; private final MetricsSystem metricsSystem; + private final MiningParameters miningParameters; public ProtocolScheduleBuilder( - final GenesisConfigOptions config, - final BigInteger defaultChainId, - final ProtocolSpecAdapters protocolSpecAdapters, - final PrivacyParameters privacyParameters, - final boolean isRevertReasonEnabled, - final EvmConfiguration evmConfiguration, - final MiningParameters miningParameters, - final BadBlockManager badBlockManager, - final boolean isParallelTxProcessingEnabled, - final MetricsSystem metricsSystem) { - this( - config, - Optional.of(defaultChainId), - protocolSpecAdapters, - privacyParameters, - isRevertReasonEnabled, - evmConfiguration, - miningParameters, - badBlockManager, - isParallelTxProcessingEnabled, - metricsSystem); - } - - public ProtocolScheduleBuilder( - final GenesisConfigOptions config, - final ProtocolSpecAdapters protocolSpecAdapters, - final PrivacyParameters privacyParameters, - final boolean isRevertReasonEnabled, - final EvmConfiguration evmConfiguration, - final MiningParameters miningParameters, - final BadBlockManager badBlockManager, - final boolean isParallelTxProcessingEnabled, - final MetricsSystem metricsSystem) { - this( - config, - Optional.empty(), - protocolSpecAdapters, - privacyParameters, - isRevertReasonEnabled, - evmConfiguration, - miningParameters, - badBlockManager, - isParallelTxProcessingEnabled, - metricsSystem); - } - - private ProtocolScheduleBuilder( final GenesisConfigOptions config, final Optional defaultChainId, final ProtocolSpecAdapters protocolSpecAdapters, @@ -117,10 +70,10 @@ public class ProtocolScheduleBuilder { this.isRevertReasonEnabled = isRevertReasonEnabled; this.evmConfiguration = evmConfiguration; this.defaultChainId = defaultChainId; - this.miningParameters = miningParameters; this.badBlockManager = badBlockManager; this.isParallelTxProcessingEnabled = isParallelTxProcessingEnabled; this.metricsSystem = metricsSystem; + this.miningParameters = miningParameters; } public ProtocolSchedule createProtocolSchedule() { @@ -130,7 +83,7 @@ public class ProtocolScheduleBuilder { return protocolSchedule; } - private void initSchedule( + public void initSchedule( final ProtocolSchedule protocolSchedule, final Optional chainId) { final MainnetProtocolSpecFactory specFactory = @@ -557,4 +510,8 @@ public class ProtocolScheduleBuilder { TIMESTAMP } } + + public Optional getDefaultChainId() { + return defaultChainId; + } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index 511b94d3ae..e05ba21268 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -152,7 +152,7 @@ public class ExecutionContextTestFixture { protocolSchedule = new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(42), + Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java index e94c6b49fd..5eec6d61e5 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java @@ -22,10 +22,10 @@ import org.hyperledger.besu.config.JsonGenesisConfigOptions; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.io.IOException; +import java.util.Optional; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -36,9 +36,9 @@ public class ProtocolScheduleFixture { public static final ProtocolSchedule MAINNET = MainnetProtocolSchedule.fromConfig( getMainnetConfigOptions(), - PrivacyParameters.DEFAULT, - false, - EvmConfiguration.DEFAULT, + Optional.empty(), + Optional.empty(), + Optional.empty(), MiningParameters.newDefault(), new BadBlockManager(), false, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolScheduleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolScheduleTest.java index 2d5dd2cee3..e48cd67302 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DefaultProtocolScheduleTest.java @@ -56,7 +56,7 @@ public class DefaultProtocolScheduleTest { builder = new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), ProtocolSpecAdapters.create(FIRST_TIMESTAMP_FORK, modifier), privacyParameters, isRevertReasonEnabled, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilderTest.java index ad261abf47..cade5bd601 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilderTest.java @@ -62,7 +62,7 @@ class ProtocolScheduleBuilderTest { builder = new ProtocolScheduleBuilder( configOptions, - CHAIN_ID, + Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, @@ -257,7 +257,7 @@ class ProtocolScheduleBuilderTest { final ProtocolScheduleBuilder builder = new ProtocolScheduleBuilder( configOptions, - CHAIN_ID, + Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(blockNumber, modifier), new PrivacyParameters(), false, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java index c3ca24a4e1..07d4e6ab4b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java @@ -178,7 +178,7 @@ public abstract class AbstractTransactionPoolTestBase { final ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), - BigInteger.valueOf(1), + Optional.of(BigInteger.valueOf(1)), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), false, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index 5742637c3e..d1bafc3969 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -373,7 +373,7 @@ public class TransactionPoolFactoryTest { schedule = new ProtocolScheduleBuilder( config, - DEFAULT_CHAIN_ID, + Optional.of(DEFAULT_CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, false, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java index 8dc8a74c1f..8490312d81 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java @@ -187,7 +187,7 @@ class MainnetGenesisFileModule extends GenesisFileModule { return () -> new ProtocolScheduleBuilder( options, - options.getChainId().orElse(BigInteger.ONE), + options.getChainId(), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, false, diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index 48f556a5b9..5fbab994cf 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -191,6 +191,8 @@ dependencies { implementation 'io.tmio:tuweni-rlp' implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' + implementation 'com.google.dagger:dagger' + annotationProcessor 'com.google.dagger:dagger-compiler' referenceTestImplementation project(path: ':config') referenceTestImplementation project(path: ':datatypes') diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java index 976c8e70d2..b9af680fe3 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java @@ -34,6 +34,7 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -151,7 +152,7 @@ public class ReferenceTestProtocolSchedules { private static ProtocolSchedule createSchedule(final GenesisConfigOptions options) { return new ProtocolScheduleBuilder( options, - CHAIN_ID, + Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, false, diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java index cfb56d1ebc..3a61967044 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java @@ -61,64 +61,64 @@ public class DifficultyCalculatorTests { MainnetProtocolSchedule.fromConfig( GenesisConfigFile.mainnet() .withOverrides(postMergeOverrides).getConfigOptions(), - EvmConfiguration.DEFAULT, MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem())), + EvmConfiguration.DEFAULT, MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem())), Arguments.of( "/DifficultyTests/dfGrayGlacier/difficultyGrayGlacierForkBlock.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfGrayGlacier/difficultyGrayGlacierTimeDiff1.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfGrayGlacier/difficultyGrayGlacierTimeDiff2.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().grayGlacierBlock(15050000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfArrowGlacier/difficultyArrowGlacierForkBlock.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfArrowGlacier/difficultyArrowGlacierTimeDiff1.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfArrowGlacier/difficultyArrowGlacierTimeDiff2.json", MainnetProtocolSchedule.fromConfig( - new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + new StubGenesisConfigOptions().arrowGlacierBlock(13773000), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfByzantium/difficultyByzantium.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().byzantiumBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().byzantiumBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfConstantinople/difficultyConstantinople.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().constantinopleBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().constantinopleBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfEIP2384/difficultyEIP2384.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfEIP2384/difficultyEIP2384_random.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfEIP2384/difficultyEIP2384_random_to20M.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().muirGlacierBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfFrontier/difficultyFrontier.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions(), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions(), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) ), Arguments.of( "/DifficultyTests/dfHomestead/difficultyHomestead.json", - MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().homesteadBlock(0), MiningParameters.newDefault(), new BadBlockManager(), false, new NoOpMetricsSystem()) + MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().homesteadBlock(0), MiningParameters.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()) )); } diff --git a/ethereum/retesteth/build.gradle b/ethereum/retesteth/build.gradle deleted file mode 100644 index 484953a391..0000000000 --- a/ethereum/retesteth/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -apply plugin: 'java-library' - -jar { - archiveBaseName = 'besu-retesteth' - manifest { - attributes( - 'Specification-Title': archiveBaseName, - 'Specification-Version': project.version, - 'Implementation-Title': archiveBaseName, - 'Implementation-Version': calculateVersion(), - 'Commit-Hash': getGitCommitDetails(40).hash - ) - } -} - -dependencies { - api 'org.slf4j:slf4j-api' - - implementation project(':config') - implementation project(':datatypes') - implementation project(':ethereum:api') - implementation project(':ethereum:api') - implementation project(':ethereum:blockcreation') - implementation project(':ethereum:core') - implementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') - implementation project(':ethereum:eth') - implementation project(':ethereum:p2p') - implementation project(':ethereum:rlp') - implementation project(':evm') - implementation project(':metrics:core') - implementation project(':nat') - implementation project(':services:kvstore') - implementation project(':util') - - implementation 'com.google.guava:guava' - implementation 'io.vertx:vertx-core' - implementation 'io.vertx:vertx-web' - implementation 'com.fasterxml.jackson.core:jackson-databind' - implementation 'io.tmio:tuweni-bytes' - implementation 'io.tmio:tuweni-units' - - testImplementation 'org.assertj:assertj-core' - testImplementation 'org.junit.jupiter:junit-jupiter' - testImplementation 'org.mockito:mockito-core' -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java deleted file mode 100644 index db1ac943f0..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/NoRewardProtocolScheduleWrapper.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth; - -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.BlockValidator; -import org.hyperledger.besu.ethereum.MainnetBlockValidator; -import org.hyperledger.besu.ethereum.chain.BadBlockManager; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockImporter; -import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter; -import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; -import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; -import org.hyperledger.besu.ethereum.mainnet.MainnetBlockImporter; -import org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; -import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; - -import java.math.BigInteger; -import java.util.Optional; -import java.util.function.Predicate; - -public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule { - - private final ProtocolSchedule delegate; - private final BadBlockManager badBlockManager; - - NoRewardProtocolScheduleWrapper( - final ProtocolSchedule delegate, final BadBlockManager badBlockManager) { - this.delegate = delegate; - this.badBlockManager = badBlockManager; - } - - @Override - public ProtocolSpec getByBlockHeader(final ProcessableBlockHeader blockHeader) { - final ProtocolSpec original = delegate.getByBlockHeader(blockHeader); - final BlockProcessor noRewardBlockProcessor = - new MainnetBlockProcessor( - original.getTransactionProcessor(), - original.getTransactionReceiptFactory(), - Wei.ZERO, - original.getMiningBeneficiaryCalculator(), - original.isSkipZeroBlockRewards(), - delegate); - final BlockValidator noRewardBlockValidator = - new MainnetBlockValidator( - original.getBlockHeaderValidator(), - original.getBlockBodyValidator(), - noRewardBlockProcessor, - badBlockManager); - final BlockImporter noRewardBlockImporter = new MainnetBlockImporter(noRewardBlockValidator); - return new ProtocolSpec( - original.getName(), - original.getEvm(), - original.getTransactionValidatorFactory(), - original.getTransactionProcessor(), - original.getPrivateTransactionProcessor(), - original.getBlockHeaderValidator(), - original.getOmmerHeaderValidator(), - original.getBlockBodyValidator(), - noRewardBlockProcessor, - noRewardBlockImporter, - noRewardBlockValidator, - original.getBlockHeaderFunctions(), - original.getTransactionReceiptFactory(), - original.getDifficultyCalculator(), - Wei.ZERO, // block reward - original.getMiningBeneficiaryCalculator(), - original.getPrecompileContractRegistry(), - original.isSkipZeroBlockRewards(), - original.getGasCalculator(), - original.getGasLimitCalculator(), - original.getFeeMarket(), - Optional.empty(), - original.getWithdrawalsValidator(), - original.getWithdrawalsProcessor(), - original.getRequestsValidator(), - original.getRequestProcessorCoordinator(), - original.getBlockHashProcessor(), - original.isPoS(), - original.isReplayProtectionSupported()); - } - - @Override - public boolean anyMatch(final Predicate predicate) { - return delegate.anyMatch(predicate); - } - - @Override - public boolean isOnMilestoneBoundary(final BlockHeader blockHeader) { - return delegate.isOnMilestoneBoundary(blockHeader); - } - - @Override - public Optional getChainId() { - return delegate.getChainId(); - } - - @Override - public void putBlockNumberMilestone(final long blockNumber, final ProtocolSpec protocolSpec) { - delegate.putBlockNumberMilestone(blockNumber, protocolSpec); - } - - @Override - public void putTimestampMilestone(final long timestamp, final ProtocolSpec protocolSpec) { - delegate.putTimestampMilestone(timestamp, protocolSpec); - } - - @Override - public Optional hardforkFor( - final Predicate predicate) { - return delegate.hardforkFor(predicate); - } - - @Override - public String listMilestones() { - return delegate.listMilestones(); - } - - @Override - public void setPermissionTransactionFilter( - final PermissionTransactionFilter permissionTransactionFilter) { - delegate.setPermissionTransactionFilter(permissionTransactionFilter); - } - - @Override - public void setPublicWorldStateArchiveForPrivacyBlockProcessor( - final WorldStateArchive publicWorldStateArchive) { - delegate.setPublicWorldStateArchiveForPrivacyBlockProcessor(publicWorldStateArchive); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethClock.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethClock.java deleted file mode 100644 index fdd22f42b0..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethClock.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.util.Optional; - -public class RetestethClock extends Clock { - - private Optional fixedInstant; - private final Clock delegateClock; - - RetestethClock() { - this(Clock.systemUTC()); - } - - private RetestethClock(final Clock delegateClock) { - fixedInstant = Optional.empty(); - this.delegateClock = delegateClock; - } - - @Override - public ZoneId getZone() { - return delegateClock.getZone(); - } - - @Override - public Clock withZone(final ZoneId zone) { - final RetestethClock zonedClock = new RetestethClock(delegateClock.withZone(zone)); - zonedClock.fixedInstant = fixedInstant; - return zonedClock; - } - - @Override - public Instant instant() { - return fixedInstant.orElseGet(delegateClock::instant); - } - - public void resetTime(final long time) { - fixedInstant = Optional.of(Instant.ofEpochSecond(time)); - } - - public void advanceSeconds(final long seconds) { - fixedInstant = Optional.of(Instant.ofEpochSecond(instant().getEpochSecond() + seconds)); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java deleted file mode 100644 index 32d4e0bab1..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth; - -import static org.hyperledger.besu.config.JsonUtil.normalizeKeys; - -import org.hyperledger.besu.config.JsonGenesisConfigOptions; -import org.hyperledger.besu.config.JsonUtil; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay; -import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; -import org.hyperledger.besu.ethereum.chain.BadBlockManager; -import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; -import org.hyperledger.besu.ethereum.chain.GenesisState; -import org.hyperledger.besu.ethereum.chain.MutableBlockchain; -import org.hyperledger.besu.ethereum.chain.VariablesStorage; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; -import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues; -import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.Unstable; -import org.hyperledger.besu.ethereum.core.MiningParameters; -import org.hyperledger.besu.ethereum.core.MutableWorldState; -import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; -import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthMessages; -import org.hyperledger.besu.ethereum.eth.manager.EthPeers; -import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; -import org.hyperledger.besu.ethereum.eth.sync.SyncMode; -import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; -import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; -import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory; -import org.hyperledger.besu.ethereum.forkid.ForkIdManager; -import org.hyperledger.besu.ethereum.mainnet.EpochCalculator; -import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; -import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.PoWHasher; -import org.hyperledger.besu.ethereum.mainnet.PoWSolution; -import org.hyperledger.besu.ethereum.mainnet.PoWSolver; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; -import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; -import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; -import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; -import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive; -import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; -import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; -import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; -import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.MetricsSystem; -import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; -import org.hyperledger.besu.util.Subscribers; -import org.hyperledger.besu.util.number.Fraction; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Supplier; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RetestethContext { - - private static final Logger LOG = LoggerFactory.getLogger(RetestethContext.class); - private static final PoWHasher NO_WORK_HASHER = - (final long nonce, final long number, EpochCalculator epochCalc, final Bytes headerHash) -> - new PoWSolution(nonce, Hash.ZERO, UInt256.ZERO, Hash.ZERO); - public static final int MAX_PEERS = 25; - - private final ReentrantLock contextLock = new ReentrantLock(); - private final BadBlockManager badBlockManager = new BadBlockManager(); - private Address coinbase; - private Bytes extraData; - private MutableBlockchain blockchain; - private ProtocolContext protocolContext; - private BlockchainQueries blockchainQueries; - private ProtocolSchedule protocolSchedule; - private BlockHeaderFunctions blockHeaderFunctions; - private HeaderValidationMode headerValidationMode; - private BlockReplay blockReplay; - private RetestethClock retestethClock; - private MiningParameters miningParameters; - private TransactionPool transactionPool; - private EthScheduler ethScheduler; - private PoWSolver poWSolver; - - private Optional terminalTotalDifficulty; - private Optional mixHash; - - public boolean resetContext( - final String genesisConfigString, final String sealEngine, final Optional clockTime) { - contextLock.lock(); - try { - tearDownContext(); - return buildContext(genesisConfigString, sealEngine, clockTime); - } catch (final Exception e) { - LOG.error("Error shutting down existing runner", e); - return false; - } finally { - contextLock.unlock(); - } - } - - private void tearDownContext() { - try { - if (ethScheduler != null) { - ethScheduler.stop(); - ethScheduler.awaitStop(); - } - } catch (final InterruptedException e) { - throw new RuntimeException(e); - } - } - - private boolean buildContext( - final String genesisConfigString, final String sealEngine, final Optional clockTime) { - final ObjectNode genesisConfig = - normalizeKeys(JsonUtil.objectNodeFromString(genesisConfigString)); - - retestethClock = new RetestethClock(); - clockTime.ifPresent(retestethClock::resetTime); - final MetricsSystem metricsSystem = new NoOpMetricsSystem(); - - terminalTotalDifficulty = - Optional.ofNullable(genesisConfig.get("params")) - .map(n -> n.get("terminaltotaldifficulty")) - .map(JsonNode::asText) - .map(Bytes::fromHexString); - - final JsonGenesisConfigOptions jsonGenesisConfigOptions = - JsonGenesisConfigOptions.fromJsonObject( - JsonUtil.getObjectNode(genesisConfig, "config").get()); - protocolSchedule = - MainnetProtocolSchedule.fromConfig( - jsonGenesisConfigOptions, - EvmConfiguration.DEFAULT, - miningParameters, - badBlockManager, - false, - new NoOpMetricsSystem()); - if ("NoReward".equalsIgnoreCase(sealEngine)) { - protocolSchedule = new NoRewardProtocolScheduleWrapper(protocolSchedule, badBlockManager); - } - blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); - - final GenesisState genesisState = GenesisState.fromJson(genesisConfigString, protocolSchedule); - coinbase = genesisState.getBlock().getHeader().getCoinbase(); - extraData = genesisState.getBlock().getHeader().getExtraData(); - mixHash = Optional.ofNullable(genesisState.getBlock().getHeader().getMixHashOrPrevRandao()); - - final WorldStateArchive worldStateArchive = - new ForestWorldStateArchive( - new WorldStateStorageCoordinator( - new ForestWorldStateKeyValueStorage(new InMemoryKeyValueStorage())), - new WorldStatePreimageKeyValueStorage(new InMemoryKeyValueStorage()), - EvmConfiguration.DEFAULT); - final MutableWorldState worldState = worldStateArchive.getMutable(); - genesisState.writeStateTo(worldState); - - blockchain = createInMemoryBlockchain(genesisState.getBlock()); - protocolContext = new ProtocolContext(blockchain, worldStateArchive, null, badBlockManager); - - blockchainQueries = - new BlockchainQueries( - protocolSchedule, blockchain, worldStateArchive, ethScheduler, miningParameters); - - final String sealengine = JsonUtil.getString(genesisConfig, "sealengine", ""); - headerValidationMode = - "NoProof".equals(sealengine) || "NoReward".equals(sealEngine) - ? HeaderValidationMode.LIGHT - : HeaderValidationMode.FULL; - - miningParameters = - ImmutableMiningParameters.builder() - .mutableInitValues( - MutableInitValues.builder() - .coinbase(coinbase) - .extraData(extraData) - .targetGasLimit(blockchain.getChainHeadHeader().getGasLimit()) - .minBlockOccupancyRatio(0.0) - .minTransactionGasPrice(Wei.ZERO) - .build()) - .unstable(Unstable.builder().powJobTimeToLive(1000).maxOmmerDepth(8).build()) - .build(); - miningParameters.setMinTransactionGasPrice(Wei.ZERO); - poWSolver = - ("NoProof".equals(sealengine) || "NoReward".equals(sealEngine)) - ? new PoWSolver( - miningParameters, - NO_WORK_HASHER, - false, - Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator()) - : new PoWSolver( - miningParameters, - PoWHasher.ETHASH_LIGHT, - false, - Subscribers.none(), - new EpochCalculator.DefaultEpochCalculator()); - - blockReplay = - new BlockReplay(protocolSchedule, protocolContext, blockchainQueries.getBlockchain()); - - final Bytes localNodeKey = Bytes.wrap(new byte[64]); - - // mining support - - final Supplier currentProtocolSpecSupplier = - () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()); - final EthPeers ethPeers = - new EthPeers( - "reteseth", - currentProtocolSpecSupplier, - retestethClock, - metricsSystem, - EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, - Collections.emptyList(), - localNodeKey, - MAX_PEERS, - MAX_PEERS, - false, - SyncMode.FAST, - new ForkIdManager(blockchain, List.of(), List.of(), false)); - final SyncState syncState = new SyncState(blockchain, ethPeers); - - ethScheduler = new EthScheduler(1, 1, 1, 1, metricsSystem); - final EthContext ethContext = new EthContext(ethPeers, new EthMessages(), ethScheduler); - - final TransactionPoolConfiguration transactionPoolConfiguration = - ImmutableTransactionPoolConfiguration.builder() - .txPoolLimitByAccountPercentage(Fraction.fromFloat(0.004f)) - .build(); - - transactionPool = - TransactionPoolFactory.createTransactionPool( - protocolSchedule, - protocolContext, - ethContext, - retestethClock, - metricsSystem, - syncState, - transactionPoolConfiguration, - new BlobCache(), - MiningParameters.newDefault()); - - if (LOG.isTraceEnabled()) { - LOG.trace("Genesis Block {} ", genesisState.getBlock()); - } - - return true; - } - - private static MutableBlockchain createInMemoryBlockchain(final Block genesisBlock) { - return createInMemoryBlockchain(genesisBlock, new MainnetBlockHeaderFunctions()); - } - - private static MutableBlockchain createInMemoryBlockchain( - final Block genesisBlock, final BlockHeaderFunctions blockHeaderFunctions) { - final InMemoryKeyValueStorage keyValueStorage = new InMemoryKeyValueStorage(); - final VariablesStorage variablesStorage = - new VariablesKeyValueStorage(new InMemoryKeyValueStorage()); - return DefaultBlockchain.createMutable( - genesisBlock, - new KeyValueStoragePrefixedKeyBlockchainStorage( - keyValueStorage, variablesStorage, blockHeaderFunctions, false), - new NoOpMetricsSystem(), - 100); - } - - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - public BlockHeaderFunctions getBlockHeaderFunctions() { - return blockHeaderFunctions; - } - - public ProtocolContext getProtocolContext() { - return protocolContext; - } - - public EthScheduler getEthScheduler() { - return ethScheduler; - } - - public void setEthScheduler(final EthScheduler ethScheduler) { - this.ethScheduler = ethScheduler; - } - - public long getBlockHeight() { - return blockchain.getChainHeadBlockNumber(); - } - - public ProtocolSpec getProtocolSpec(final BlockHeader blockHeader) { - return getProtocolSchedule().getByBlockHeader(blockHeader); - } - - public BlockHeader getBlockHeader(final long blockNumber) { - return blockchain.getBlockHeader(blockNumber).get(); - } - - public BlockchainQueries getBlockchainQueries() { - return blockchainQueries; - } - - public HeaderValidationMode getHeaderValidationMode() { - return headerValidationMode; - } - - BlockReplay getBlockReplay() { - return blockReplay; - } - - public TransactionPool getTransactionPool() { - return transactionPool; - } - - public MiningParameters getMiningParameters() { - return miningParameters; - } - - public MutableBlockchain getBlockchain() { - return blockchain; - } - - public RetestethClock getRetestethClock() { - return retestethClock; - } - - public Optional getTerminalTotalDifficulty() { - return terminalTotalDifficulty; - } - - public Optional getMixHash() { - return mixHash; - } - - public PoWSolver getEthHashSolver() { - return poWSolver; - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethService.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethService.java deleted file mode 100644 index 877c597686..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethService.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth; - -import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; -import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcHttpService; -import org.hyperledger.besu.ethereum.api.jsonrpc.health.HealthService; -import org.hyperledger.besu.ethereum.api.jsonrpc.health.LivenessCheck; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugAccountRange; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugStorageRangeAt; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthBlockNumber; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBalance; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockByHash; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockByNumber; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetCode; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetTransactionCount; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthSendRawTransaction; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Web3ClientVersion; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; -import org.hyperledger.besu.ethereum.core.DummySynchronizer; -import org.hyperledger.besu.ethereum.core.Synchronizer; -import org.hyperledger.besu.ethereum.retesteth.methods.TestGetLogHash; -import org.hyperledger.besu.ethereum.retesteth.methods.TestImportRawBlock; -import org.hyperledger.besu.ethereum.retesteth.methods.TestMineBlocks; -import org.hyperledger.besu.ethereum.retesteth.methods.TestModifyTimestamp; -import org.hyperledger.besu.ethereum.retesteth.methods.TestRewindToBlock; -import org.hyperledger.besu.ethereum.retesteth.methods.TestSetChainParams; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.nat.NatService; - -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -import io.vertx.core.Vertx; - -public class RetestethService { - - private final JsonRpcHttpService jsonRpcHttpService; - private final Vertx vertx; - - private final RetestethContext retestethContext; - - public RetestethService( - final String clientVersion, - final RetestethConfiguration retestethConfiguration, - final JsonRpcConfiguration jsonRpcConfiguration) { - vertx = Vertx.vertx(); - retestethContext = new RetestethContext(); - - final BlockResultFactory blockResult = new BlockResultFactory(); - final NatService natService = new NatService(Optional.empty()); - - // Synchronizer needed by RPC methods. Didn't wanna mock it, since this isn't the test module. - Synchronizer sync = new DummySynchronizer(); - - final Map jsonRpcMethods = - mapOf( - new Web3ClientVersion(clientVersion), - new TestSetChainParams(retestethContext), - new TestImportRawBlock(retestethContext), - new EthBlockNumber(retestethContext::getBlockchainQueries, true), - new EthGetBlockByNumber( - retestethContext::getBlockchainQueries, blockResult, sync, true), - new DebugAccountRange(retestethContext::getBlockchainQueries), - new EthGetBalance(retestethContext::getBlockchainQueries), - new EthGetBlockByHash(retestethContext::getBlockchainQueries, blockResult, true), - new EthGetCode(retestethContext::getBlockchainQueries), - new EthGetTransactionCount( - retestethContext::getBlockchainQueries, retestethContext::getTransactionPool), - new DebugStorageRangeAt( - retestethContext::getBlockchainQueries, retestethContext::getBlockReplay, true), - new TestModifyTimestamp(retestethContext), - new EthSendRawTransaction(retestethContext::getTransactionPool, true), - new TestMineBlocks(retestethContext), - new TestGetLogHash(retestethContext), - new TestRewindToBlock(retestethContext)); - - jsonRpcHttpService = - new JsonRpcHttpService( - vertx, - retestethConfiguration.getDataPath(), - jsonRpcConfiguration, - new NoOpMetricsSystem(), - natService, - jsonRpcMethods, - new HealthService(new LivenessCheck()), - HealthService.ALWAYS_HEALTHY); - } - - public void start() { - jsonRpcHttpService.start(); - } - - public void close() { - stop(); - } - - public void stop() { - jsonRpcHttpService.stop(); - vertx.close(); - } - - private static Map mapOf(final JsonRpcMethod... rpcMethods) { - return Arrays.stream(rpcMethods) - .collect(Collectors.toMap(JsonRpcMethod::getName, rpcMethod -> rpcMethod)); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestGetLogHash.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestGetLogHash.java deleted file mode 100644 index 398d72d665..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestGetLogHash.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; -import org.hyperledger.besu.ethereum.rlp.RLP; -import org.hyperledger.besu.evm.log.Log; - -import java.util.Optional; - -public class TestGetLogHash implements JsonRpcMethod { - private final RetestethContext context; - - public TestGetLogHash(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return "test_getLogHash"; - } - - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - final Hash txHash; - try { - txHash = requestContext.getRequiredParameter(0, Hash.class); - } catch (JsonRpcParameterException e) { - throw new InvalidJsonRpcParameters( - "Invalid transaction hash parameter (index 0)", - RpcErrorType.INVALID_TRANSACTION_HASH_PARAMS, - e); - } - - final Optional receipt = - context - .getBlockchainQueries() - .transactionReceiptByTransactionHash(txHash, context.getProtocolSchedule()); - return new JsonRpcSuccessResponse( - requestContext.getRequest().getId(), - receipt.map(this::calculateLogHash).orElse(Hash.EMPTY_LIST_HASH).toString()); - } - - private Hash calculateLogHash( - final TransactionReceiptWithMetadata transactionReceiptWithMetadata) { - return Hash.hash( - RLP.encode( - out -> - out.writeList( - transactionReceiptWithMetadata.getReceipt().getLogsList(), Log::writeTo))); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java deleted file mode 100644 index 580b107a8b..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlock.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockImporter; -import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; -import org.hyperledger.besu.ethereum.rlp.RLP; -import org.hyperledger.besu.ethereum.rlp.RLPException; - -import java.util.Collections; - -import org.apache.tuweni.bytes.Bytes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TestImportRawBlock implements JsonRpcMethod { - private static final Logger LOG = LoggerFactory.getLogger(TestImportRawBlock.class); - - public static final String METHOD_NAME = "test_importRawBlock"; - - private final RetestethContext context; - - public TestImportRawBlock(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return METHOD_NAME; - } - - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - final String input; - try { - input = requestContext.getRequiredParameter(0, String.class); - } catch (JsonRpcParameterException e) { - throw new InvalidJsonRpcParameters( - "Invalid block parameter (index 0)", RpcErrorType.INVALID_BLOCK_PARAMS, e); - } - final ProtocolContext protocolContext = this.context.getProtocolContext(); - - final Block block; - try { - block = - Block.readFrom(RLP.input(Bytes.fromHexString(input)), context.getBlockHeaderFunctions()); - } catch (final RLPException | IllegalArgumentException e) { - LOG.debug("Failed to parse block RLP", e); - return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), RpcErrorType.BLOCK_RLP_IMPORT_ERROR); - } - - // retesteth expects test_rawImportBlock to not only import the block, but append it to head - if (context.getBlockchain().contains(block.getHash())) { - // if we already have the block but it is not head, append it: - context - .getBlockchain() - .appendBlock( - block, - context - .getBlockchain() - .getTxReceipts(block.getHash()) - .orElse(Collections.emptyList())); - } else { - // otherwise attempt to import the block - final BlockImporter blockImporter = - context.getProtocolSpec(block.getHeader()).getBlockImporter(); - final BlockImportResult result = - blockImporter.importBlock( - protocolContext, - block, - context.getHeaderValidationMode(), - context.getHeaderValidationMode()); - if (!result.isImported()) { - LOG.debug("Failed to import block."); - return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), RpcErrorType.BLOCK_IMPORT_ERROR); - } - } - // return success on append or import - return new JsonRpcSuccessResponse( - requestContext.getRequest().getId(), block.getHash().toString()); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java deleted file mode 100644 index 00a27bb7a8..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.blockcreation.PoWBlockCreator; -import org.hyperledger.besu.ethereum.chain.MutableBlockchain; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockImporter; -import org.hyperledger.besu.ethereum.core.MiningParameters; -import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; -import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; -import org.hyperledger.besu.ethereum.retesteth.RetestethClock; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; - -public class TestMineBlocks implements JsonRpcMethod { - private final RetestethContext context; - - public TestMineBlocks(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return "test_mineBlocks"; - } - - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - long blocksToMine = 0; - try { - blocksToMine = requestContext.getRequiredParameter(0, Long.class); - } catch (JsonRpcParameterException e) { - throw new InvalidJsonRpcParameters( - "Invalid blocks to mine (index 0)", RpcErrorType.INVALID_BLOCK_COUNT_PARAMS, e); - } - while (blocksToMine-- > 0) { - if (!mineNewBlock()) { - return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), false); - } - } - - return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), true); - } - - private boolean mineNewBlock() { - final RetestethClock retesethClock = context.getRetestethClock(); - final ProtocolSchedule protocolSchedule = context.getProtocolSchedule(); - final ProtocolContext protocolContext = context.getProtocolContext(); - final MutableBlockchain blockchain = context.getBlockchain(); - final HeaderValidationMode headerValidationMode = context.getHeaderValidationMode(); - final MiningParameters miningParameters = context.getMiningParameters(); - final PoWBlockCreator blockCreator = - new PoWBlockCreator( - miningParameters, - header -> miningParameters.getExtraData(), - context.getTransactionPool(), - protocolContext, - protocolSchedule, - context.getEthHashSolver(), - context.getEthScheduler()); - final Block block = - blockCreator - .createBlock(retesethClock.instant().getEpochSecond(), blockchain.getChainHeadHeader()) - .getBlock(); - - // advance clock so next mine won't hit the same timestamp - retesethClock.advanceSeconds(1); - - final BlockImporter blockImporter = - protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()).getBlockImporter(); - final BlockImportResult result = - blockImporter.importBlock( - protocolContext, block, headerValidationMode, headerValidationMode); - return result.isImported(); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestModifyTimestamp.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestModifyTimestamp.java deleted file mode 100644 index 717cf41b45..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestModifyTimestamp.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; - -public class TestModifyTimestamp implements JsonRpcMethod { - - private final RetestethContext context; - - public TestModifyTimestamp(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return "test_modifyTimestamp"; - } - - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - final long epochSeconds; - try { - epochSeconds = requestContext.getRequiredParameter(0, Long.class); - } catch (JsonRpcParameterException e) { - throw new InvalidJsonRpcParameters( - "Invalid timestamp parameter (index 0)", RpcErrorType.INVALID_TIMESTAMP_PARAMS, e); - } - context.getRetestethClock().resetTime(epochSeconds); - return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), true); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestRewindToBlock.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestRewindToBlock.java deleted file mode 100644 index d9b847af42..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestRewindToBlock.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; - -public class TestRewindToBlock implements JsonRpcMethod { - private final RetestethContext context; - - public static final String METHOD_NAME = "test_rewindToBlock"; - - public TestRewindToBlock(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return METHOD_NAME; - } - - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - final long blockNumber; - try { - blockNumber = requestContext.getRequiredParameter(0, Long.TYPE); - } catch (JsonRpcParameterException e) { - throw new InvalidJsonRpcParameters( - "Invalid block number parameter (index 0)", RpcErrorType.INVALID_BLOCK_NUMBER_PARAMS, e); - } - - return new JsonRpcSuccessResponse( - requestContext.getRequest().getId(), context.getBlockchain().rewindToBlock(blockNumber)); - } -} diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParams.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParams.java deleted file mode 100644 index 1446fd939f..0000000000 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParams.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; - -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; - -import io.vertx.core.json.JsonObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TestSetChainParams implements JsonRpcMethod { - - private static final Logger LOG = LoggerFactory.getLogger(TestSetChainParams.class); - - public static final String METHOD_NAME = "test_setChainParams"; - private final RetestethContext context; - - public TestSetChainParams(final RetestethContext context) { - this.context = context; - } - - @Override - public String getName() { - return METHOD_NAME; - } - - @SuppressWarnings("unchecked") - @Override - public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { - - try { - final JsonObject chainParamsAsJson = - new JsonObject((Map) requestContext.getRequest().getParams()[0]); - final String chainParamsAsString = chainParamsAsJson.encodePrettily(); - LOG.trace("ChainParams {}", chainParamsAsString); - final String genesisFileAsString = modifyGenesisFile(chainParamsAsString); - LOG.trace("Genesis {}", genesisFileAsString); - final boolean result = - context.resetContext( - genesisFileAsString, - chainParamsAsJson.getString("sealEngine", "NoProof"), - Optional.empty()); - - return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result); - } catch (final Exception e) { - LOG.error("Unhandled error", e); - return new JsonRpcErrorResponse( - requestContext.getRequest().getId(), RpcErrorType.INVALID_PARAMS); - } - } - - private static void maybeMove( - final JsonObject src, final String srcName, final JsonObject dest, final String destName) { - if (src.containsKey(srcName)) { - dest.put(destName, src.getValue(srcName)); - src.remove(srcName); - } - } - - private static void maybeMoveToNumber( - final JsonObject src, final String srcName, final JsonObject dest, final String destName) { - if (src.containsKey(srcName)) { - dest.put(destName, Long.decode(src.getString(srcName))); - src.remove(srcName); - } - } - - private static void maybeMoveToNumber( - final JsonObject src, - final String srcName, - final JsonObject dest, - final String destName, - final long defaultValue) { - if (src.containsKey(srcName)) { - dest.put(destName, Long.decode(src.getString(srcName))); - src.remove(srcName); - } else { - dest.put(destName, defaultValue); - } - } - - private static String modifyGenesisFile(final String initialGenesis) { - final JsonObject chainParamsJson = new JsonObject(initialGenesis); - final JsonObject config = new JsonObject(); - chainParamsJson.put("config", config); - final JsonObject params = chainParamsJson.getJsonObject("params"); - final JsonObject genesis = chainParamsJson.getJsonObject("genesis"); - - // Whether sealEngine is NoProof, Ethash, or NoReward the genesis file is the same - final JsonObject ethash = new JsonObject(); - config.put("ethash", ethash); - - maybeMoveToNumber(params, "homesteadForkBlock", config, "homesteadBlock"); - maybeMoveToNumber(params, "daoHardforkBlock", config, "daoForkBlock"); - maybeMoveToNumber(params, "EIP150ForkBlock", config, "eip150Block"); - maybeMoveToNumber(params, "EIP158ForkBlock", config, "eip158Block"); - maybeMoveToNumber(params, "byzantiumForkBlock", config, "byzantiumBlock"); - maybeMoveToNumber(params, "constantinopleForkBlock", config, "constantinopleBlock"); - maybeMoveToNumber(params, "constantinopleFixForkBlock", config, "petersburgBlock"); - maybeMoveToNumber(params, "istanbulForkBlock", config, "istanbulBlock"); - maybeMoveToNumber(params, "muirGlacierForkBlock", config, "muirGlacierBlock"); - maybeMoveToNumber(params, "berlinForkBlock", config, "berlinBlock"); - maybeMoveToNumber(params, "londonForkBlock", config, "londonBlock"); - maybeMoveToNumber(params, "arrowGlacierForkBlock", config, "arrowGlacierBlock"); - maybeMoveToNumber(params, "grayGlacierForkBlock", config, "grayGlacierBlock"); - maybeMoveToNumber(params, "mergeNetSplitForkBlock", config, "mergeNetSplitBlock"); - maybeMoveToNumber(params, "shanghaiForkTime", config, "shanghaiTime"); - maybeMoveToNumber(params, "cancunForkTime", config, "cancunTime"); - maybeMoveToNumber(params, "pragueForkTime", config, "pragueTime"); - maybeMoveToNumber(params, "futureEipsForkTime", config, "futureEipsTime"); - maybeMoveToNumber(params, "experimentalEipsForkTime", config, "experimentalEipsTime"); - maybeMoveToNumber(params, "chainID", config, "chainId", 1); - - maybeMove(genesis, "author", chainParamsJson, "coinbase"); - maybeMove(genesis, "difficulty", chainParamsJson, "difficulty"); - maybeMove(genesis, "extraData", chainParamsJson, "extraData"); - maybeMove(genesis, "gasLimit", chainParamsJson, "gasLimit"); - maybeMove(genesis, "mixHash", chainParamsJson, "mixHash"); - maybeMove(genesis, "nonce", chainParamsJson, "nonce"); - maybeMove(genesis, "timestamp", chainParamsJson, "timestamp"); - maybeMove(chainParamsJson, "accounts", chainParamsJson, "alloc"); - maybeMove(genesis, "baseFeePerGas", chainParamsJson, "baseFeePerGas"); - - // strip out precompiles with zero balance - final JsonObject alloc = chainParamsJson.getJsonObject("alloc"); - final Iterator fieldNamesIter = alloc.fieldNames().iterator(); - while (fieldNamesIter.hasNext()) { - final String address = fieldNamesIter.next(); - final JsonObject account = alloc.getJsonObject(address); - if (account.containsKey("precompiled") && !account.containsKey("balance")) { - fieldNamesIter.remove(); - } - } - - return chainParamsJson.encodePrettily(); - } -} diff --git a/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlockTest.java b/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlockTest.java deleted file mode 100644 index b156f2294d..0000000000 --- a/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestImportRawBlockTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; -import org.hyperledger.besu.plugin.services.rpc.RpcResponseType; - -import java.io.IOException; - -import com.google.common.base.Charsets; -import com.google.common.io.Resources; -import io.vertx.core.json.JsonObject; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class TestImportRawBlockTest { - private TestImportRawBlock test_importRawBlock; - private TestRewindToBlock test_rewindToBlock; - private RetestethContext context; - - @BeforeEach - public void setupClass() throws IOException { - context = new RetestethContext(); - test_importRawBlock = new TestImportRawBlock(context); - test_rewindToBlock = new TestRewindToBlock(context); - final TestSetChainParams test_setChainParams = new TestSetChainParams(context); - final String chainParamsJsonString = - Resources.toString( - TestSetChainParamsTest.class.getResource("multimpleBalanceInstructionChainParams.json"), - Charsets.UTF_8); - final JsonObject chainParamsJson = new JsonObject(chainParamsJsonString); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestSetChainParams.METHOD_NAME, new Object[] {chainParamsJson.getMap()})); - - assertThat(test_setChainParams.response(request)) - .isEqualTo(new JsonRpcSuccessResponse(null, true)); - } - - @Test - public void testMissingParent() { - final String rawBlockRLPString = - "0xf9045df901f9a0e38bef3dadb98e856ea82c7e9813b76a6ec8d9cf60694dd65d800a1669c1a1fda03770bba814f8cc5534ab5e40bdb3fe51866b537805c5577888091766e621fc13948888f1f195afa192cfee860698584c030f4c9db1a019ce64082807650d3d01ac60cd16a583e9472dcc0ccb8f39dd867e317cf025dda09735e49acaddb4d8338ed33df8dd006449b20b85e89e47224ac8ec8f7ea26071a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000483301fd28252088454c99c2142a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f86003018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba0a7b7f2fa93025fc1e6aa18c1aa07c32a456439754e196cb74f2f7d12cf3e840da02078cf840fb25fc3d858b2a85b622f21be0588b5c5d81d433427f6470e06a4a7f901faf901f7a0f88512d9e022357594866c44ecaa2fc9cb48f34d1987e401109400761aeb898da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794bcde5374fce5edbc8e2a8697c15331677e6ebf0ba0fe87abb0d3ab38d4eb64405de03db5245b0d40c4b85d8a1b5028ada8643de2dba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000002833007cf808454c9945142a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"; - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestImportRawBlock.METHOD_NAME, new Object[] {rawBlockRLPString})); - - final var response = test_importRawBlock.response(request); - assertThat(response.getType()).isEqualTo(RpcResponseType.ERROR); - assertThat(((JsonRpcErrorResponse) response).getErrorType()) - .isEqualTo(RpcErrorType.BLOCK_IMPORT_ERROR); - } - - @Test - public void testBadBlock() { - final String rawBlockRLPString = "0xf9045df901f9a08"; - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestImportRawBlock.METHOD_NAME, new Object[] {rawBlockRLPString})); - - final var response = test_importRawBlock.response(request); - assertThat(response.getType()).isEqualTo(RpcResponseType.ERROR); - assertThat(((JsonRpcErrorResponse) response).getErrorType()) - .isEqualTo(RpcErrorType.BLOCK_RLP_IMPORT_ERROR); - } - - @Test - public void testGoodBlock() { - final String rawBlockRLPString = - "0xf90262f901faa0e38bef3dadb98e856ea82c7e9813b76a6ec8d9cf60694dd65d800a1669c1a1fda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06e6be3f633fe0399cb17a9d8238b988a39bd9ab3e0ac0820f4df705a1ee37536a06fb77a9ddaa64a8e161b643d05533a4093f2be900ad06279b1b56b3bcee3b979a04b33fa3c9c50b7b9a4500f5c0b1e71ab43362abc81c2cf31fd2b54acf7d750d8b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba83016b66845db7320980a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a830249f094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba0d42a045ac77a6d4676dd5fbc5104ed7471b6cef2465cfefaa52919b340f942a9a06e4d319aea79e45cde79d337e6edf849ceac505cab65dd41a572cab132d4dccac0"; - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestImportRawBlock.METHOD_NAME, new Object[] {rawBlockRLPString})); - - final var response = test_importRawBlock.response(request); - assertThat(response.getType()).isEqualTo(RpcResponseType.SUCCESS); - } - - @Test - public void testReimportExistingBlock() { - final String rawBlockRLPString = - "0xf90262f901faa0e38bef3dadb98e856ea82c7e9813b76a6ec8d9cf60694dd65d800a1669c1a1fda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a06e6be3f633fe0399cb17a9d8238b988a39bd9ab3e0ac0820f4df705a1ee37536a06fb77a9ddaa64a8e161b643d05533a4093f2be900ad06279b1b56b3bcee3b979a04b33fa3c9c50b7b9a4500f5c0b1e71ab43362abc81c2cf31fd2b54acf7d750d8b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba83016b66845db7320980a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a830249f094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba0d42a045ac77a6d4676dd5fbc5104ed7471b6cef2465cfefaa52919b340f942a9a06e4d319aea79e45cde79d337e6edf849ceac505cab65dd41a572cab132d4dccac0"; - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestImportRawBlock.METHOD_NAME, new Object[] {rawBlockRLPString})); - - final JsonRpcRequestContext requestRewind = - new JsonRpcRequestContext( - new JsonRpcRequest("2.0", TestRewindToBlock.METHOD_NAME, new Object[] {0L})); - - final var response = test_importRawBlock.response(request); - assertThat(response.getType()).isEqualTo(RpcResponseType.SUCCESS); - final var rewindResponse = test_rewindToBlock.response(requestRewind); - assertThat(rewindResponse.getType()).isEqualTo(RpcResponseType.SUCCESS); - final var reimportResponse = test_importRawBlock.response(request); - assertThat(reimportResponse.getType()).isEqualTo(RpcResponseType.SUCCESS); - - assertThat(context.getBlockchain().getChainHead().getHeight()).isEqualTo(1L); - } -} diff --git a/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParamsTest.java b/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParamsTest.java deleted file mode 100644 index f376fa0c25..0000000000 --- a/ethereum/retesteth/src/test/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParamsTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.retesteth.methods; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.retesteth.RetestethContext; - -import java.io.IOException; - -import com.google.common.base.Charsets; -import com.google.common.io.Resources; -import io.vertx.core.json.JsonObject; -import org.apache.tuweni.units.bigints.UInt256; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class TestSetChainParamsTest { - - private static RetestethContext context; - private static TestSetChainParams test_setChainParams; - - @BeforeAll - public static void setupClass() { - context = new RetestethContext(); - test_setChainParams = new TestSetChainParams(context); - } - - @Test - public void testValidateGenesisImport() throws IOException { - final String chainParamsJsonString = - Resources.toString( - TestSetChainParamsTest.class.getResource("multimpleBalanceInstructionChainParams.json"), - Charsets.UTF_8); - final JsonObject chainParamsJson = new JsonObject(chainParamsJsonString); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestSetChainParams.METHOD_NAME, new Object[] {chainParamsJson.getMap()})); - - assertThat(test_setChainParams.response(request)) - .isEqualTo(new JsonRpcSuccessResponse(null, true)); - - final BlockHeader blockHeader = context.getBlockHeader(0); - - assertThat(blockHeader.getLogsBloom().toString()) - .isEqualTo( - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - assertThat(blockHeader.getCoinbase().toString()) - .isEqualTo("0x8888f1f195afa192cfee860698584c030f4c9db1"); - assertThat(blockHeader.getDifficulty()).isEqualTo(UInt256.fromHexString("0x20000")); - assertThat(blockHeader.getExtraData().toHexString()).isEqualTo("0x42"); - assertThat(blockHeader.getGasLimit()).isEqualTo(3141592); - assertThat(blockHeader.getGasUsed()).isEqualTo(0); - assertThat(blockHeader.getMixHash().toString()) - .isEqualTo("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); - assertThat(blockHeader.getNonce()).isEqualTo(0x0102030405060708L); - assertThat(blockHeader.getNumber()).isEqualTo(0); - assertThat(blockHeader.getParentHash().toString()) - .isEqualTo("0x0000000000000000000000000000000000000000000000000000000000000000"); - assertThat(blockHeader.getReceiptsRoot().toString()) - .isEqualTo("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); - assertThat(blockHeader.getStateRoot().toString()) - .isEqualTo("0xf403922bfd555a9223f68fc755564004e20d78bb42aae647e867e3b23c48beba"); - assertThat(blockHeader.getTimestamp()).isEqualTo(0x54c98c81); - assertThat(blockHeader.getTransactionsRoot().toString()) - .isEqualTo("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); - assertThat(blockHeader.getOmmersHash().toString()) - .isEqualTo("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); - } - - @Test - public void testValidate1559GenesisImport() throws IOException { - final String chainParamsJsonString = - Resources.toString( - TestSetChainParamsTest.class.getResource("1559ChainParams.json"), Charsets.UTF_8); - final JsonObject chainParamsJson = new JsonObject(chainParamsJsonString); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", TestSetChainParams.METHOD_NAME, new Object[] {chainParamsJson.getMap()})); - - assertThat(test_setChainParams.response(request)) - .isEqualTo(new JsonRpcSuccessResponse(null, true)); - - final BlockHeader blockHeader = context.getBlockHeader(0); - assertThat(blockHeader.getDifficulty()).isEqualTo(UInt256.fromHexString("0x20000")); - assertThat(blockHeader.getGasLimit()).isEqualTo(1234L); - assertThat(blockHeader.getBaseFee()).hasValue(Wei.of(12345L)); - assertThat(blockHeader.getExtraData().toHexString()).isEqualTo("0x00"); - assertThat(blockHeader.getTimestamp()).isEqualTo(0l); - assertThat(blockHeader.getNonce()).isEqualTo(0L); - assertThat(blockHeader.getMixHash().toHexString()) - .isEqualTo("0x0000000000000000000000000000000000000000000000000000000000000000"); - } -} diff --git a/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/1559ChainParams.json b/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/1559ChainParams.json deleted file mode 100644 index 95535e269f..0000000000 --- a/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/1559ChainParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "genesis" : { - "author" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "difficulty" : "0x020000", - "gasLimit" : "0x04d2", - "baseFeePerGas" : "0x3039", - "extraData" : "0x00", - "timestamp" : "0x00", - "nonce" : "0x0000000000000000", - "mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "params": { - "EIP150ForkBlock": "0x00", - "EIP158ForkBlock": "0x00", - "byzantiumForkBlock": "0x00", - "homesteadForkBlock": "0x00", - "londonForkBlock": "0x00" - }, - "sealEngine": "NoProof", - "accounts": {} -} \ No newline at end of file diff --git a/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/multimpleBalanceInstructionChainParams.json b/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/multimpleBalanceInstructionChainParams.json deleted file mode 100644 index 0cb0cfc960..0000000000 --- a/ethereum/retesteth/src/test/resources/org/hyperledger/besu/ethereum/retesteth/methods/multimpleBalanceInstructionChainParams.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "accounts": { - "0x0000000000000000000000000000000000000001": { - "precompiled": { - "linear": { - "base": 3000, - "word": 0 - }, - "name": "ecrecover" - } - }, - "0x0000000000000000000000000000000000000002": { - "precompiled": { - "linear": { - "base": 60, - "word": 12 - }, - "name": "sha256" - } - }, - "0x0000000000000000000000000000000000000003": { - "precompiled": { - "linear": { - "base": 600, - "word": 120 - }, - "name": "sha256" - } - }, - "0x0000000000000000000000000000000000000004": { - "precompiled": { - "linear": { - "base": 15, - "word": 3 - }, - "name": "identity" - } - }, - "0x0000000000000000000000000000000000000005": { - "precompiled": { - "name": "modexp" - } - }, - "0x0000000000000000000000000000000000000006": { - "precompiled": { - "linear": { - "base": 500, - "word": 0 - }, - "name": "alt_bn128_G1_add" - } - }, - "0x0000000000000000000000000000000000000007": { - "precompiled": { - "linear": { - "base": 40000, - "word": 0 - }, - "name": "alt_bn128_G1_mul" - } - }, - "0x0000000000000000000000000000000000000008": { - "precompiled": { - "name": "alt_bn128_pairing_product" - } - }, - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": { - "balance": "0x0186a0", - "code": "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0b31600055738888f1f195afa192cfee860698584c030f4c9db13160015573a94f5374fce5edbc8e2a8697c15331677e6ebf0b31600255738888f1f195afa192cfee860698584c030f4c9db13160035573095e7baea6a6c7c4c2dfeb977efac326af552d8731600555", - "nonce": "0x00", - "storage": {} - }, - "0x195e7baea6a6c7c4c2dfeb977efac326af552d87": { - "balance": "0x0186a0", - "code": "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0b31600055738888f1f195afa192cfee860698584c030f4c9db13160015573a94f5374fce5edbc8e2a8697c15331677e6ebf0b31600255738888f1f195afa192cfee860698584c030f4c9db13160035573095e7baea6a6c7c4c2dfeb977efac326af552d873160045573195e7baea6a6c7c4c2dfeb977efac326af552d8731600555", - "nonce": "0x00", - "storage": {} - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x1748721582", - "code": "0x", - "nonce": "0x00", - "storage": {} - } - }, - "genesis": { - "author": "0x8888f1f195afa192cfee860698584c030f4c9db1", - "difficulty": "0x020000", - "extraData": "0x42", - "gasLimit": "0x2fefd8", - "mixHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "nonce": "0x0102030405060708", - "timestamp": "0x54c98c81" - }, - "params": { - "EIP150ForkBlock": "0x00", - "EIP158ForkBlock": "0x00", - "byzantiumForkBlock": "0x00", - "homesteadForkBlock": "0x00" - }, - "sealEngine": "NoProof" -} \ No newline at end of file diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java index b0a31793bc..6596268acb 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImpl.java @@ -14,31 +14,80 @@ */ package org.hyperledger.besu.metrics; +import static com.google.common.base.Preconditions.checkNotNull; + +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; -import java.util.ArrayList; -import java.util.List; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; /** The Metric category registry implementation. */ public class MetricCategoryRegistryImpl implements MetricCategoryRegistry { - - private final List metricCategories = new ArrayList<>(); + private final Map metricCategories = new HashMap<>(); + private MetricsConfiguration metricsConfiguration; /** Default constructor */ public MetricCategoryRegistryImpl() {} /** - * Gets metric categories. + * Add Metrics categories. + * + * @param the type parameter + * @param categoryEnum the category enum + */ + public & MetricCategory> void addCategories(final Class categoryEnum) { + EnumSet.allOf(categoryEnum).forEach(this::addMetricCategory); + } + + /** + * Add registry category. * - * @return the metric categories + * @param metricCategory the metric category */ - public List getMetricCategories() { - return metricCategories; + @Override + public void addMetricCategory(final MetricCategory metricCategory) { + metricCategories.put(metricCategory.getName().toUpperCase(Locale.ROOT), metricCategory); } @Override - public void addMetricCategory(final MetricCategory newMetricCategory) { - metricCategories.add(newMetricCategory); + public boolean isMetricCategoryEnabled(final MetricCategory metricCategory) { + checkNotNull( + metricsConfiguration, "Metrics configuration must be set before calling this method"); + return (metricsConfiguration.isEnabled() || metricsConfiguration.isPushEnabled()) + && metricsConfiguration.getMetricCategories().contains(metricCategory); + } + + /** + * Return true if a category with that name is already registered + * + * @param name the category name + * @return true if a category with that name is already registered + */ + public boolean containsMetricCategory(final String name) { + return metricCategories.containsKey(name.toUpperCase(Locale.ROOT)); + } + + /** + * Return a metric category by name + * + * @param name the category name + * @return the metric category or null if not registered + */ + public MetricCategory getMetricCategory(final String name) { + return metricCategories.get(name.toUpperCase(Locale.ROOT)); + } + + /** + * Set the metric configuration via a method since it is still not available when creating this + * object + * + * @param metricsConfiguration the metrics configuration + */ + public void setMetricsConfiguration(final MetricsConfiguration metricsConfiguration) { + this.metricsConfiguration = metricsConfiguration; } } diff --git a/metrics/core/src/test/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImplTest.java b/metrics/core/src/test/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImplTest.java new file mode 100644 index 0000000000..b2da02f480 --- /dev/null +++ b/metrics/core/src/test/java/org/hyperledger/besu/metrics/MetricCategoryRegistryImplTest.java @@ -0,0 +1,66 @@ +/* + * Copyright contributors to 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.metrics; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; + +import java.util.Set; + +import org.junit.jupiter.api.Test; + +class MetricCategoryRegistryImplTest { + + @Test + void metricCategoryIsEnabledAndMetricsAreEnabled() { + final var registry = new MetricCategoryRegistryImpl(); + registry.addMetricCategory(BesuMetricCategory.BLOCKCHAIN); + final var metricsConfiguration = + MetricsConfiguration.builder() + .enabled(true) + .metricCategories(Set.of(BesuMetricCategory.BLOCKCHAIN)) + .build(); + registry.setMetricsConfiguration(metricsConfiguration); + assertTrue(registry.isMetricCategoryEnabled(BesuMetricCategory.BLOCKCHAIN)); + } + + @Test + void metricCategoryIsDisabledAndMetricsAreEnabled() { + final var registry = new MetricCategoryRegistryImpl(); + registry.addMetricCategory(BesuMetricCategory.ETHEREUM); + final var metricsConfiguration = + MetricsConfiguration.builder() + .enabled(true) + .metricCategories(Set.of(BesuMetricCategory.ETHEREUM)) + .build(); + registry.setMetricsConfiguration(metricsConfiguration); + assertFalse(registry.isMetricCategoryEnabled(BesuMetricCategory.BLOCKCHAIN)); + } + + @Test + void metricCategoryNotEnabledWhenMetricsAreDisabled() { + final var registry = new MetricCategoryRegistryImpl(); + registry.addMetricCategory(BesuMetricCategory.BLOCKCHAIN); + final var metricsConfiguration = + MetricsConfiguration.builder() + .enabled(false) + .metricCategories(Set.of(BesuMetricCategory.BLOCKCHAIN)) + .build(); + registry.setMetricsConfiguration(metricsConfiguration); + assertFalse(registry.isMetricCategoryEnabled(BesuMetricCategory.BLOCKCHAIN)); + } +} diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index 3632bb5ae1..c7ec672867 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -71,7 +71,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'uNQzVjMa7m1fw3d10NuVOjmzGxmCkgZd88yGFgP3qoY=' + knownHash = '8rPIE3fYl48RPRQXxYhMk559e/r+wHSKU9bGSJmruKQ=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.java index d6e460aa2f..1f84953460 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.java @@ -29,5 +29,13 @@ public interface MetricCategoryRegistry extends BesuService { * * @param newMetricCategory The {@link MetricCategory} that is being registered. */ - public void addMetricCategory(final MetricCategory newMetricCategory); + void addMetricCategory(final MetricCategory newMetricCategory); + + /** + * Return true if the metrics are enabled and the metric category is enabled + * + * @param metricCategory the metric category + * @return true if the metrics are enabled and the metric category is enabled + */ + boolean isMetricCategoryEnabled(final MetricCategory metricCategory); }